Big migration.
This commit is contained in:
Generated
+879
-640
File diff suppressed because it is too large
Load Diff
@@ -290,7 +290,7 @@ public class AstUtil {
|
||||
return new JsBinaryOperation(JsBinaryOperator.OR, op1, op2);
|
||||
}
|
||||
|
||||
//TODO
|
||||
//TODO refactor
|
||||
public static void setQualifier(JsExpression selector, JsExpression receiver) {
|
||||
if (selector instanceof JsInvocation) {
|
||||
setQualifier(((JsInvocation) selector).getQualifier(), receiver);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.jetbrains.k2js;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.dart.compiler.backend.js.ast.JsProgram;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
@@ -17,6 +18,7 @@ import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
|
||||
import org.jetbrains.jet.plugin.JetLanguage;
|
||||
import org.jetbrains.k2js.generate.CodeGenerator;
|
||||
import org.jetbrains.k2js.translate.general.Translation;
|
||||
@@ -25,18 +27,23 @@ import org.jetbrains.k2js.utils.GenerationUtils;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getNamespaceDescriptor;
|
||||
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getNameForNamespace;
|
||||
import static org.jetbrains.k2js.utils.JetTestUtils.analyzeNamespace;
|
||||
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
*/
|
||||
public final class K2JSTranslator {
|
||||
|
||||
private static final List<String> LIB_FILE_NAMES = Arrays.asList(
|
||||
"C:\\Dev\\Projects\\Kotlin\\jet\\stdlib\\ktSrc\\jssupport\\JsCollectionSupport.jet",
|
||||
"C:\\Dev\\Projects\\Kotlin\\jet\\stdlib\\ktSrc\\jssupport\\JsSupport.jet"
|
||||
);
|
||||
|
||||
@NotNull
|
||||
private JetCoreEnvironment environment = new JetCoreEnvironment(new Disposable() {
|
||||
|
||||
@@ -55,9 +62,18 @@ public final class K2JSTranslator {
|
||||
public K2JSTranslator() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JetFile> getJsSupportStdLib() {
|
||||
List<JetFile> libFiles = new ArrayList<JetFile>();
|
||||
for (String libFileName : LIB_FILE_NAMES) {
|
||||
libFiles.add(loadPsiFile(libFileName));
|
||||
}
|
||||
return libFiles;
|
||||
}
|
||||
|
||||
public void translateFile(@NotNull String inputFile, @NotNull String outputFile) throws Exception {
|
||||
JetFile PsiFile = loadPsiFile(inputFile);
|
||||
includeRtJar();
|
||||
// includeRtJar();
|
||||
JsProgram program = generateProgram(PsiFile);
|
||||
CodeGenerator generator = new CodeGenerator();
|
||||
generator.generateToFile(program, new File(outputFile));
|
||||
@@ -83,8 +99,21 @@ public final class K2JSTranslator {
|
||||
@NotNull
|
||||
private JsProgram generateProgram(@NotNull JetFile psiFile) {
|
||||
|
||||
bindingContext = analyzeNamespace(psiFile,
|
||||
JetControlFlowDataTraceFactory.EMPTY);
|
||||
// bindingContext = analyzeNamespace(psiFile,
|
||||
// JetControlFlowDataTraceFactory.EMPTY);
|
||||
List<JetFile> files = getJsSupportStdLib();
|
||||
files.add(psiFile);
|
||||
bindingContext = AnalyzerFacade.analyzeFilesWithJavaIntegration(psiFile.getProject(), files, new Predicate<PsiFile>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable PsiFile file) {
|
||||
for (String libFileName : LIB_FILE_NAMES) {
|
||||
if (libFileName.contains(file.getName().substring(0, file.getName().lastIndexOf('.')))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, JetControlFlowDataTraceFactory.EMPTY);
|
||||
assert bindingContext != null;
|
||||
AnalyzingUtils.checkForSyntacticErrors(psiFile);
|
||||
AnalyzingUtils.throwExceptionOnErrors(bindingContext);
|
||||
|
||||
@@ -19,6 +19,7 @@ import static org.jetbrains.k2js.translate.utils.DescriptorUtils.*;
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
*/
|
||||
//TODO: REFACTOR FFS
|
||||
public final class StandardClasses {
|
||||
|
||||
//TODO: move declaration code to some kind of builder
|
||||
@@ -31,22 +32,32 @@ public final class StandardClasses {
|
||||
declareRange(standardClasses);
|
||||
declareString(standardClasses);
|
||||
declareJavaArrayList(standardClasses);
|
||||
declareJavaSystem(standardClasses);
|
||||
declareJavaInteger(standardClasses);
|
||||
declareJavaUtilIterator(standardClasses);
|
||||
declareTopLevelFunctions(standardClasses);
|
||||
declareInteger(standardClasses);
|
||||
return standardClasses;
|
||||
}
|
||||
|
||||
private static void declareJavaUtilIterator(@NotNull StandardClasses standardClasses) {
|
||||
String iteratorFQName = "<java_root>.java.util.Iterator";
|
||||
standardClasses.declareStandardTopLevelObject(iteratorFQName, "Iterator");
|
||||
declareMethods(standardClasses, iteratorFQName, "next", "hasNext");
|
||||
//TODO: refactor
|
||||
private static void declareTopLevelFunctions(@NotNull StandardClasses standardClasses) {
|
||||
String parseIntFQName = "js.parseInt";
|
||||
standardClasses.declareStandardTopLevelObject(parseIntFQName, "parseInt");
|
||||
String printlnFQName = "js.println";
|
||||
standardClasses.declareStandardTopLevelObject(printlnFQName, "println");
|
||||
String printFQName = "js.print";
|
||||
standardClasses.declareStandardTopLevelObject(printFQName, "print");
|
||||
}
|
||||
|
||||
private static void declareInteger(@NotNull StandardClasses standardClasses) {
|
||||
String integerFQName = "Integer";
|
||||
standardClasses.declareStandardTopLevelObject(integerFQName, "Integer");
|
||||
standardClasses.declareStandardInnerDeclaration(integerFQName, "parseInt", "parseInt");
|
||||
}
|
||||
|
||||
|
||||
private static void declareString(@NotNull StandardClasses standardClasses) {
|
||||
String stringFQName = "jet.String";
|
||||
standardClasses.declareStandardTopLevelObject(stringFQName, "String");
|
||||
standardClasses.declareStandardInnerDeclaration(stringFQName, "length", "length");
|
||||
declareReadonlyProperties(standardClasses, stringFQName, "length");
|
||||
}
|
||||
|
||||
//TODO: duplication
|
||||
@@ -55,27 +66,12 @@ public final class StandardClasses {
|
||||
standardClasses.declareStandardTopLevelObject(intRangeFQName, "NumberRange");
|
||||
standardClasses.declareStandardInnerDeclaration(intRangeFQName, "<init>", "NumberRange");
|
||||
declareMethods(standardClasses, intRangeFQName, "iterator", "contains");
|
||||
declareProperties(standardClasses, intRangeFQName, "start", "size", "end", "reversed");
|
||||
declareReadonlyProperties(standardClasses, intRangeFQName, "start", "size", "end", "reversed");
|
||||
}
|
||||
|
||||
private static void declareJavaInteger(@NotNull StandardClasses standardClasses) {
|
||||
String integerFQName = "<java_root>.java.lang.Integer";
|
||||
standardClasses.declareStandardTopLevelObject(integerFQName, "Integer");
|
||||
declareMethods(standardClasses, integerFQName, "parseInt");
|
||||
}
|
||||
|
||||
private static void declareJavaSystem(@NotNull StandardClasses standardClasses) {
|
||||
String systemFQName = "<java_root>.java.lang.System";
|
||||
standardClasses.declareStandardTopLevelObject(systemFQName, "System");
|
||||
declareMethods(standardClasses, systemFQName, "out");
|
||||
String printStreamFQName = "<java_root>.java.io.PrintStream";
|
||||
//TODO:
|
||||
standardClasses.declareStandardTopLevelObject(printStreamFQName, "ErrorName");
|
||||
declareMethods(standardClasses, printStreamFQName, "print", "println");
|
||||
}
|
||||
|
||||
private static void declareJavaArrayList(@NotNull StandardClasses standardClasses) {
|
||||
String arrayListFQName = "<java_root>.java.util.ArrayList";
|
||||
String arrayListFQName = "java.util.ArrayList";
|
||||
standardClasses.declareStandardTopLevelObject(arrayListFQName, "ArrayList");
|
||||
standardClasses.declareStandardInnerDeclaration(arrayListFQName, "<init>", "ArrayList");
|
||||
declareMethods(standardClasses, arrayListFQName, "size", "add", "get",
|
||||
@@ -113,12 +109,16 @@ public final class StandardClasses {
|
||||
}
|
||||
}
|
||||
|
||||
private static void declareProperties(@NotNull StandardClasses standardClasses,
|
||||
@NotNull String classFQName,
|
||||
@NotNull String... propertyNames) {
|
||||
private static void declareReadonlyProperties(@NotNull StandardClasses standardClasses,
|
||||
@NotNull String classFQName,
|
||||
@NotNull String... propertyNames) {
|
||||
for (String propertyName : propertyNames) {
|
||||
standardClasses.declareStandardInnerDeclaration(classFQName,
|
||||
propertyName, Namer.getNameForGetter(propertyName));
|
||||
propertyName, propertyName);
|
||||
//TODO: provide general and concise way to declare
|
||||
// standardClasses.declareStandardInnerDeclaration(classFQName,
|
||||
// "get-" + propertyName, propertyName);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,16 +2,14 @@ package org.jetbrains.k2js.translate.intrinsic;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorVisitor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lexer.JetToken;
|
||||
import org.jetbrains.k2js.translate.intrinsic.array.ArrayGetIntrinsic;
|
||||
import org.jetbrains.k2js.translate.intrinsic.array.ArrayNullConstructorIntrinsic;
|
||||
import org.jetbrains.k2js.translate.intrinsic.array.ArraySetIntrinsic;
|
||||
import org.jetbrains.k2js.translate.intrinsic.primitive.*;
|
||||
import org.jetbrains.k2js.translate.intrinsic.string.LengthIntrinsic;
|
||||
import org.jetbrains.k2js.translate.operation.OperatorTable;
|
||||
import org.jetbrains.k2js.translate.utils.DescriptorUtils;
|
||||
|
||||
@@ -20,6 +18,7 @@ import java.util.Map;
|
||||
|
||||
import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.*;
|
||||
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getFunctionByName;
|
||||
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getPropertyByName;
|
||||
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
@@ -48,10 +47,17 @@ public final class Intrinsics {
|
||||
private Intrinsics(@NotNull JetStandardLibrary library) {
|
||||
this.library = library;
|
||||
declareOperatorIntrinsics();
|
||||
declareStringIntrinsics();
|
||||
//TODO: array intrinsic are under consideration
|
||||
//declareArrayIntrinsics();
|
||||
}
|
||||
|
||||
private void declareStringIntrinsics() {
|
||||
PropertyDescriptor lengthProperty =
|
||||
getPropertyByName(library.getString().getDefaultType().getMemberScope(), "length");
|
||||
functionIntrinsics.put(lengthProperty.getGetter(), LengthIntrinsic.INSTANCE);
|
||||
}
|
||||
|
||||
private void declareOperatorIntrinsics() {
|
||||
IntrinsicDeclarationVisitor visitor = new IntrinsicDeclarationVisitor();
|
||||
for (DeclarationDescriptor descriptor : library.getLibraryScope().getAllDescriptors()) {
|
||||
@@ -70,6 +76,7 @@ public final class Intrinsics {
|
||||
|
||||
FunctionDescriptor setFunction = getFunctionByName(library.getArray(), "set");
|
||||
functionIntrinsics.put(setFunction, ArraySetIntrinsic.INSTANCE);
|
||||
|
||||
}
|
||||
|
||||
public boolean isIntrinsic(@NotNull DeclarationDescriptor descriptor) {
|
||||
|
||||
+1
-1
@@ -36,6 +36,6 @@ public final class IntrinsicArrayUtils {
|
||||
@NotNull
|
||||
private static JsExpression throwOutOfBoundsException() {
|
||||
//TODO: think about exception
|
||||
return new JsThisRef();
|
||||
return AstUtil.newQualifiedNameRef("ErrorName");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.jetbrains.k2js.translate.intrinsic.string;
|
||||
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||
import com.google.dart.compiler.backend.js.ast.JsNameRef;
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||
import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
*/
|
||||
public enum LengthIntrinsic implements FunctionIntrinsic {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsExpression apply(@NotNull JsExpression receiver, @NotNull List<JsExpression> arguments,
|
||||
@NotNull TranslationContext context) {
|
||||
assert arguments.isEmpty() : "Length expression must have zero arguments.";
|
||||
//TODO: provide better way
|
||||
JsNameRef lengthProperty = AstUtil.newQualifiedNameRef("length");
|
||||
AstUtil.setQualifier(lengthProperty, receiver);
|
||||
return lengthProperty;
|
||||
}
|
||||
}
|
||||
@@ -126,9 +126,16 @@ public final class CallTranslator extends AbstractTranslator {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsExpression translate(@NotNull JsExpression receiver, @NotNull CallableDescriptor functionDescriptor,
|
||||
public static JsExpression translate(@Nullable JsExpression receiver, @NotNull CallableDescriptor functionDescriptor,
|
||||
@NotNull TranslationContext context) {
|
||||
return (new CallTranslator(receiver, Collections.<JsExpression>emptyList(), functionDescriptor, context)).translate();
|
||||
return translate(receiver, Collections.<JsExpression>emptyList(), functionDescriptor, context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsExpression translate(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments,
|
||||
@NotNull CallableDescriptor functionDescriptor,
|
||||
@NotNull TranslationContext context) {
|
||||
return (new CallTranslator(receiver, arguments, functionDescriptor, context)).translate();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+4
-50
@@ -1,8 +1,6 @@
|
||||
package org.jetbrains.k2js.translate.reference;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||
import com.google.dart.compiler.backend.js.ast.JsInvocation;
|
||||
import com.google.dart.compiler.backend.js.ast.JsName;
|
||||
import com.google.dart.compiler.backend.js.ast.JsNameRef;
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -14,10 +12,11 @@ import org.jetbrains.jet.lang.descriptors.PropertySetterDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||
import org.jetbrains.k2js.translate.general.Translation;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getDescriptorForReferenceExpression;
|
||||
import static org.jetbrains.k2js.translate.utils.PsiUtils.getSelectorAsSimpleName;
|
||||
import static org.jetbrains.k2js.translate.utils.PsiUtils.isBackingFieldReference;
|
||||
@@ -32,7 +31,6 @@ public final class PropertyAccessTranslator extends AccessTranslator {
|
||||
private static final String MESSAGE = "Cannot be accessor call. Use canBeProperty*Call to ensure this method " +
|
||||
"can be called safely.";
|
||||
|
||||
|
||||
@NotNull
|
||||
private static PropertyDescriptor getPropertyDescriptor(@NotNull JetSimpleNameExpression expression,
|
||||
@NotNull TranslationContext context) {
|
||||
@@ -42,13 +40,6 @@ public final class PropertyAccessTranslator extends AccessTranslator {
|
||||
return (PropertyDescriptor) descriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsExpression translateAsPropertyGetterCall(@NotNull JetQualifiedExpression expression,
|
||||
@NotNull TranslationContext context) {
|
||||
return (newInstance(expression, context))
|
||||
.translateAsGet();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsExpression translateAsPropertyGetterCall(@NotNull PropertyDescriptor descriptor,
|
||||
@NotNull TranslationContext context) {
|
||||
@@ -163,15 +154,7 @@ public final class PropertyAccessTranslator extends AccessTranslator {
|
||||
|
||||
@NotNull
|
||||
private JsExpression getterCall() {
|
||||
//TODO: HACK to make standard example work
|
||||
if (DescriptorUtils.getFQName(propertyDescriptor).equals("jet.String.length")) {
|
||||
JsNameRef lengthMethodReference = AstUtil.newQualifiedNameRef("length");
|
||||
AstUtil.setQualifier(lengthMethodReference, translateQualifier());
|
||||
return lengthMethodReference;
|
||||
}
|
||||
|
||||
JsName getterName = getGetterName();
|
||||
return qualifiedAccessorInvocation(getterName);
|
||||
return CallTranslator.translate(translateQualifier(), getGetterDescriptor(), context());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -186,10 +169,7 @@ public final class PropertyAccessTranslator extends AccessTranslator {
|
||||
|
||||
@NotNull
|
||||
private JsExpression setterCall(@NotNull JsExpression toSetTo) {
|
||||
JsName setterName = getSetterName();
|
||||
JsInvocation setterCall = qualifiedAccessorInvocation(setterName);
|
||||
setterCall.getArguments().add(toSetTo);
|
||||
return setterCall;
|
||||
return CallTranslator.translate(translateQualifier(), Arrays.asList(toSetTo), getSetterDescriptor(), context());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -198,13 +178,6 @@ public final class PropertyAccessTranslator extends AccessTranslator {
|
||||
return AstUtil.newAssignment(backingFieldReference, toSetTo);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsInvocation qualifiedAccessorInvocation(@NotNull JsName accessorName) {
|
||||
JsNameRef accessorReference = accessorName.makeRef();
|
||||
AstUtil.setQualifier(accessorReference, translateQualifier());
|
||||
return AstUtil.newInvocation(accessorReference);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsExpression translateQualifier() {
|
||||
if (qualifier != null) {
|
||||
@@ -215,7 +188,6 @@ public final class PropertyAccessTranslator extends AccessTranslator {
|
||||
return implicitReceiver;
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
private static JetSimpleNameExpression getNotNullSelector(@NotNull JetQualifiedExpression qualifiedExpression) {
|
||||
JetSimpleNameExpression selectorExpression = getSelectorAsSimpleName(qualifiedExpression);
|
||||
@@ -223,18 +195,6 @@ public final class PropertyAccessTranslator extends AccessTranslator {
|
||||
return selectorExpression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsName getGetterName() {
|
||||
//TODO: hack alert. properties for standard objects that do not have their implementation
|
||||
// do not have getters and thus this workaround is needed
|
||||
if (context().isStandardObject(propertyDescriptor)) {
|
||||
return context().getNameForStandardObject(propertyDescriptor);
|
||||
}
|
||||
|
||||
PropertyGetterDescriptor getter = getGetterDescriptor();
|
||||
return context().getNameForDescriptor(getter);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PropertyGetterDescriptor getGetterDescriptor() {
|
||||
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
|
||||
@@ -242,12 +202,6 @@ public final class PropertyAccessTranslator extends AccessTranslator {
|
||||
return getter;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsName getSetterName() {
|
||||
PropertySetterDescriptor setter = getSetterDescriptor();
|
||||
return context().getNameForDescriptor(setter);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PropertySetterDescriptor getSetterDescriptor() {
|
||||
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
|
||||
|
||||
@@ -46,7 +46,7 @@ public class FunctionTest extends AbstractExpressionTest {
|
||||
|
||||
@Test
|
||||
public void closureWithParameter() throws Exception {
|
||||
testFooBoxIsOk("closureWithParameter.jet");
|
||||
testFooBoxIsOk("closureWithParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -56,7 +56,7 @@ public class FunctionTest extends AbstractExpressionTest {
|
||||
|
||||
@Test
|
||||
public void enclosingThis() throws Exception {
|
||||
testFunctionOutput("enclosingThis.jet", "Anonymous", "box", "OK");
|
||||
testFunctionOutput("enclosingThis.kt", "Anonymous", "box", "OK");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -32,10 +32,4 @@ public class MiscTest extends AbstractExpressionTest {
|
||||
public void safecallComputesExpressionOnlyOnce() throws Exception {
|
||||
testFooBoxIsTrue("safecallComputesExpressionOnlyOnce.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void KT962() throws Exception {
|
||||
checkOutput("KT-962.kt", "stdout\n" +
|
||||
"Hello, world!\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public class OperationTest extends AbstractExpressionTest {
|
||||
|
||||
@Test
|
||||
public void assign() throws Exception {
|
||||
testFunctionOutput("assign.jet", "foo", "f", 2.0);
|
||||
testFunctionOutput("assign.kt", "foo", "f", 2.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package org.jetbrains.k2js.test;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
*/
|
||||
public final class SystemTest extends JavaClassesTest {
|
||||
|
||||
final private static String MAIN = "system/";
|
||||
|
||||
@Override
|
||||
protected String mainDirectory() {
|
||||
return MAIN;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void systemPrint() throws Exception {
|
||||
checkOutput("print.kt", "Hello, world!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void systemPrintln() throws Exception {
|
||||
checkOutput("println.kt", "Hello, world!\n3\n\n");
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,13 @@ import org.jetbrains.k2js.K2JSTranslator;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.MappedByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@@ -18,6 +24,7 @@ public abstract class TranslationTest {
|
||||
private static final String CASES = "cases/";
|
||||
private static final String OUT = "out/";
|
||||
private static final String KOTLIN_JS_LIB = TEST_FILES + "kotlin_lib.js";
|
||||
private static final String EXPECTED = "expected/";
|
||||
|
||||
protected abstract String mainDirectory();
|
||||
|
||||
@@ -49,6 +56,14 @@ public abstract class TranslationTest {
|
||||
return testFilesPath() + casesDirectoryName();
|
||||
}
|
||||
|
||||
private String getExpectedPath() {
|
||||
return testFilesPath() + expectedDirectoryName();
|
||||
}
|
||||
|
||||
private String expectedDirectoryName() {
|
||||
return EXPECTED;
|
||||
}
|
||||
|
||||
protected void testFunctionOutput(String filename, String namespaceName,
|
||||
String functionName, Object expectedResult) throws Exception {
|
||||
translateFile(filename);
|
||||
@@ -81,6 +96,10 @@ public abstract class TranslationTest {
|
||||
return getInputFilePath(filename);
|
||||
}
|
||||
|
||||
private String expected(String testName) {
|
||||
return getExpectedPath() + testName + ".out";
|
||||
}
|
||||
|
||||
protected void runFileWithRhino(String inputFile, Context context, Scriptable scope) throws Exception {
|
||||
FileReader reader = new FileReader(inputFile);
|
||||
context.evaluateReader(scope, reader, inputFile, 1, null);
|
||||
@@ -111,4 +130,21 @@ public abstract class TranslationTest {
|
||||
new RhinoSystemOutputChecker(expectedResult, Arrays.asList(args)));
|
||||
}
|
||||
|
||||
protected void testWithMain(String testName, String testId, String... args) throws Exception {
|
||||
checkOutput(testName + ".kt", readFile(expected(testName + testId)), args);
|
||||
}
|
||||
|
||||
private static String readFile(String path) throws IOException {
|
||||
FileInputStream stream = new FileInputStream(new File(path));
|
||||
try {
|
||||
FileChannel fc = stream.getChannel();
|
||||
MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
|
||||
/* Instead of using default, pass in a decoder. */
|
||||
return Charset.defaultCharset().decode(bb).toString();
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -5,9 +5,9 @@ import org.junit.Test;
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
*/
|
||||
public final class WebDemoExamplesTest extends TranslationTest {
|
||||
public final class WebDemoExamples1Test extends TranslationTest {
|
||||
|
||||
final private static String MAIN = "webDemoExamples/";
|
||||
final private static String MAIN = "webDemoExamples1/";
|
||||
|
||||
@Override
|
||||
protected String mainDirectory() {
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.jetbrains.k2js.test;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
*/
|
||||
public final class WebDemoExamples2Test extends TranslationTest {
|
||||
|
||||
final private static String MAIN = "webDemoExamples2/";
|
||||
|
||||
@Override
|
||||
protected String mainDirectory() {
|
||||
return MAIN;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bottles() throws Exception {
|
||||
testWithMain("bottles", "");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -16,7 +16,7 @@ class N() : M() {
|
||||
|
||||
fun box(): String {
|
||||
val n = N()
|
||||
System.out?.println("a: " + n.a + " b: " + n.b + " superb: " + n.superb)
|
||||
println("a: " + n.a + " b: " + n.b + " superb: " + n.superb)
|
||||
if (n.b == 3 && n.a == 4 && n.superb == 3) return "OK";
|
||||
return "fail";
|
||||
}
|
||||
@@ -23,7 +23,7 @@ class N() : M {
|
||||
|
||||
fun box(): String {
|
||||
val n = N()
|
||||
System.out?.println("a: " + n.a + " b: " + n.b + " superb: " + n.superb)
|
||||
println("a: " + n.a + " b: " + n.b + " superb: " + n.superb)
|
||||
if (n.b == 3 && n.a == 4 && n.superb == 3) return "OK";
|
||||
return "fail";
|
||||
}
|
||||
@@ -46,8 +46,8 @@ fun lifetime(body: (Lifetime)->Unit)
|
||||
fun<T> Dump(items:ArrayList<T>)
|
||||
{
|
||||
for(item in items)
|
||||
System.out?.print(item.toString() + ", ")
|
||||
System.out?.println()
|
||||
print(item.toString() + ", ")
|
||||
println()
|
||||
}
|
||||
|
||||
fun main(args:Array<String>)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
iimport
|
||||
|
||||
fun stdout(): java.io.PrintStream? {
|
||||
System.out?.println("stdout")
|
||||
println("stdout")
|
||||
return System.out
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package foo
|
||||
|
||||
import js.*
|
||||
|
||||
class RangeIterator(val start : Int, var count : Int, val reversed : Boolean) {
|
||||
|
||||
var i = start
|
||||
@@ -59,7 +61,7 @@ fun testRange() : Boolean {
|
||||
sum += i;
|
||||
}
|
||||
for (i in oneToFive) {
|
||||
System.out?.print(i)
|
||||
print(i)
|
||||
}
|
||||
|
||||
if (sum != 10) return false;
|
||||
@@ -70,7 +72,7 @@ fun testRange() : Boolean {
|
||||
|
||||
fun testReversedRange() : Boolean {
|
||||
|
||||
System.out?.println("Testing reversed range.");
|
||||
println("Testing reversed range.");
|
||||
|
||||
val tenToFive = NumberRange(10, 5, true);
|
||||
|
||||
@@ -89,7 +91,7 @@ fun testReversedRange() : Boolean {
|
||||
if (!(tenToFive.end == 6)) return false;
|
||||
|
||||
for (i in tenToFive) {
|
||||
System.out?.println(i)
|
||||
println(i)
|
||||
}
|
||||
|
||||
|
||||
@@ -106,5 +108,5 @@ fun testReversedRange() : Boolean {
|
||||
}
|
||||
|
||||
fun main(args : Array<String>) {
|
||||
System.out?.println(box())
|
||||
println(box())
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fun main(args : Array<String>) {
|
||||
System.out?.print("Hello, world!");
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
fun main(args : Array<String>) {
|
||||
System.out?.println("Hello, world!");
|
||||
System.out?.println(3);
|
||||
System.out?.println();
|
||||
}
|
||||
@@ -280,10 +280,14 @@ Kotlin.Array = Class.create({
|
||||
size:function () {
|
||||
return this.array.length;
|
||||
},
|
||||
//TODO: remove duplicated methods
|
||||
get_size:function () {
|
||||
return this.array.length;
|
||||
},
|
||||
iterator:function () {
|
||||
return new Kotlin.ArrayIterator(this);
|
||||
},
|
||||
indices:function () {
|
||||
get_indices:function () {
|
||||
return new Kotlin.NumberRange(0, this.size(), false);
|
||||
}
|
||||
});
|
||||
@@ -358,15 +362,11 @@ Kotlin.ArrayIterator = Class.create({
|
||||
}
|
||||
});
|
||||
|
||||
Kotlin.Integer = function () {
|
||||
|
||||
return {
|
||||
parseInt:function (str) {
|
||||
return parseInt(str);
|
||||
}
|
||||
Kotlin.parseInt =
|
||||
function (str) {
|
||||
return parseInt(str);
|
||||
}
|
||||
|
||||
}();
|
||||
;
|
||||
|
||||
Kotlin.System = function () {
|
||||
var output = "";
|
||||
@@ -397,6 +397,14 @@ Kotlin.System = function () {
|
||||
};
|
||||
}();
|
||||
|
||||
Kotlin.println = function (s) {
|
||||
Kotlin.System.out().println(s);
|
||||
}
|
||||
|
||||
Kotlin.print = function (s) {
|
||||
Kotlin.System.out().print(s);
|
||||
}
|
||||
|
||||
Kotlin.AbstractFunctionInvokationError = Class.create();
|
||||
|
||||
Kotlin.Iterator = Class.create({
|
||||
@@ -420,6 +428,9 @@ Kotlin.ArrayIterator = Class.create(Kotlin.Iterator, {
|
||||
},
|
||||
hasNext:function () {
|
||||
return (this.array.size() > this.index);
|
||||
},
|
||||
get_hasNext:function () {
|
||||
return this.hasNext();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -453,6 +464,8 @@ Kotlin.RangeIterator = Kotlin.Class.create(Kotlin.Iterator, {
|
||||
}
|
||||
}, hasNext:function () {
|
||||
return this.get_count() > 0;
|
||||
}, get_hasNext:function () {
|
||||
return this.hasNext();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package foo
|
||||
|
||||
import js.*
|
||||
|
||||
fun box() : Boolean {
|
||||
|
||||
var oneToFive = IntRange(1, 4)
|
||||
@@ -21,7 +23,7 @@ fun box() : Boolean {
|
||||
sum += i;
|
||||
}
|
||||
for (i in oneToFive) {
|
||||
System.out?.print(i)
|
||||
print(i)
|
||||
}
|
||||
|
||||
if (sum != 10) return false;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package foo
|
||||
|
||||
|
||||
|
||||
fun box() : Boolean {
|
||||
|
||||
if (1 in -2..0) return false;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package foo
|
||||
|
||||
import js.*
|
||||
|
||||
fun box() : Boolean {
|
||||
|
||||
var oneToFive = 1..5
|
||||
@@ -21,7 +23,7 @@ fun box() : Boolean {
|
||||
sum += i;
|
||||
}
|
||||
for (i in oneToFive) {
|
||||
System.out?.print(i)
|
||||
print(i)
|
||||
}
|
||||
|
||||
if (sum != 15) return false;
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
fun main(args : Array<String>) {
|
||||
for (arg in args)
|
||||
System.out?.println(arg)
|
||||
|
||||
// or
|
||||
System.out?.println()
|
||||
for (i in args.indices)
|
||||
System.out?.println(args[i])
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
fun main(args : Array<String>) {
|
||||
System.out?.println(max(Integer.parseInt(args[0]), Integer.parseInt(args[1])))
|
||||
}
|
||||
|
||||
fun max(a : Int, b : Int) = if (a > b) a else b
|
||||
@@ -1,10 +0,0 @@
|
||||
fun main(args : Array<String>) {
|
||||
System.out?.println(getStringLength("aaa"))
|
||||
System.out?.println(getStringLength(1))
|
||||
}
|
||||
|
||||
fun getStringLength(obj : Any) : Int? {
|
||||
if (obj is String)
|
||||
return obj.length // no cast to String is needed
|
||||
return null
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
fun main(args : Array<String>) {
|
||||
val language = if (args.size == 0) "EN" else args[0]
|
||||
System.out?.println(when (language) {
|
||||
"EN" -> "Hello!"
|
||||
"FR" -> "Salut!"
|
||||
"IT" -> "Ciao!"
|
||||
else -> "Sorry, I can't greet you in $language yet"
|
||||
})
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
// Return null if str does not hold a number
|
||||
fun parseInt(str : String) : Int? {
|
||||
try{
|
||||
return Integer.parseInt(str)
|
||||
} catch (e: NumberFormatException) {
|
||||
System.out?.println("One of argument isn't Int")
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun main(args : Array<String>) {
|
||||
if (args.size < 2) {
|
||||
System.out?.print("No number supplied");
|
||||
} else {
|
||||
val x = parseInt(args[0])
|
||||
val y = parseInt(args[1])
|
||||
|
||||
// We cannot say 'x * y' now because they may hold nulls
|
||||
if (x != null && y != null) {
|
||||
System.out?.print(x * y) // Now we can
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
class Greeter(name : String) {
|
||||
val name = name
|
||||
fun greet() {
|
||||
System.out?.println("Hello, ${name}!");
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args : Array<String>) {
|
||||
Greeter(args[0]).greet()
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
fun main(args : Array<String>) {
|
||||
cases("Hello")
|
||||
cases(1)
|
||||
cases(MyClass())
|
||||
cases("hello")
|
||||
}
|
||||
|
||||
fun cases(obj : Any) {
|
||||
when(obj) {
|
||||
1 -> System.out?.println("One")
|
||||
"Hello" -> System.out?.println("Greeting")
|
||||
!is String -> System.out?.println("Not a string")
|
||||
else -> System.out?.println("Unknown")
|
||||
}
|
||||
}
|
||||
|
||||
class MyClass() {
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fun main(args : Array<String>) {
|
||||
System.out?.print(args[0]);
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import java.util.ArrayList;
|
||||
|
||||
fun main(args : Array<String>) {
|
||||
val x = Integer.parseInt(args[0])
|
||||
//Check if a number lies within a range:
|
||||
val y = 10
|
||||
if (x in 1..y-1)
|
||||
System.out?.println("OK")
|
||||
|
||||
//Iterate over a range:
|
||||
for (a in 1..5)
|
||||
System.out?.print(" ${a}")
|
||||
|
||||
//Check if a number is out of range:
|
||||
System.out?.println()
|
||||
val array = ArrayList<String>();
|
||||
|
||||
array.add("aaa")
|
||||
array.add("bbb")
|
||||
array.add("ccc")
|
||||
|
||||
if (x !in 0..array.size())
|
||||
System.out?.println("Out: array has only ${array.size()} elements. x = ${x}")
|
||||
|
||||
//Check if a collection contains an object:
|
||||
if ("aaa" in array) // collection.contains(obj) is called
|
||||
System.out?.println("Yes: array contains aaa")
|
||||
|
||||
if ("ddd" in array) // collection.contains(obj) is called
|
||||
System.out?.println("Yes: array contains ddd")
|
||||
else
|
||||
System.out?.println("No: array doesn't contains ddd")
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
fun main(args : Array<String>) {
|
||||
var i = 0
|
||||
while (i < args.size)
|
||||
System.out?.println(args[i++])
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* This example implements the famous "99 Bottles of Beer" program
|
||||
* See http://99-bottles-of-beer.net/
|
||||
*
|
||||
* The point is to print out a song with the following lyrics:
|
||||
*
|
||||
* The "99 bottles of beer" song
|
||||
*
|
||||
* 99 bottles of beer on the wall, 99 bottles of beer.
|
||||
* Take one down, pass it around, 98 bottles of beer on the wall.
|
||||
*
|
||||
* 98 bottles of beer on the wall, 98 bottles of beer.
|
||||
* Take one down, pass it around, 97 bottles of beer on the wall.
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* 2 bottles of beer on the wall, 2 bottles of beer.
|
||||
* Take one down, pass it around, 1 bottle of beer on the wall.
|
||||
*
|
||||
* 1 bottle of beer on the wall, 1 bottle of beer.
|
||||
* Take one down, pass it around, no more bottles of beer on the wall.
|
||||
*
|
||||
* No more bottles of beer on the wall, no more bottles of beer.
|
||||
* Go to the store and buy some more, 99 bottles of beer on the wall.
|
||||
*
|
||||
* Additionally, you can pass the desired initial number of bottles to use (rather than 99)
|
||||
* as a command-line argument
|
||||
*/
|
||||
import js.*
|
||||
|
||||
fun main(args : Array<String>) {
|
||||
if (args.isEmpty) {
|
||||
printBottles(99)
|
||||
}
|
||||
else {
|
||||
val bottles = Integer.parseInt(args[0]);
|
||||
if (bottles != null) {
|
||||
printBottles(bottles);
|
||||
} else {
|
||||
println("You have passed '${args[0]}' as a number of bottles, " +
|
||||
"but it is not a valid integral number")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun printBottles(bottleCount : Int) {
|
||||
if (bottleCount <= 0) {
|
||||
println("No bottles - no song")
|
||||
return
|
||||
}
|
||||
|
||||
println("The \"${bottlesOfBeer(bottleCount)}\" song\n")
|
||||
|
||||
var bottles = bottleCount
|
||||
while (bottles > 0) {
|
||||
val bottlesOfBeer = bottlesOfBeer(bottles)
|
||||
print("$bottlesOfBeer on the wall, $bottlesOfBeer.\nTake one down, pass it around, ")
|
||||
bottles--
|
||||
println("${bottlesOfBeer(bottles)} on the wall.\n")
|
||||
}
|
||||
println("No more bottles of beer on the wall, no more bottles of beer.\n" +
|
||||
"Go to the store and buy some more, ${bottlesOfBeer(bottleCount)} on the wall.")
|
||||
}
|
||||
|
||||
fun bottlesOfBeer(count : Int) : String =
|
||||
when (count) {
|
||||
0 -> "no more bottles"
|
||||
1 -> "1 bottle"
|
||||
else -> "$count bottles"
|
||||
} + " of beer"
|
||||
|
||||
// From the std package
|
||||
// This is an extension property, i.e. a property that is defined for the
|
||||
// type Array<T>, but does not sit inside the class Array
|
||||
val <T> Array<T>.isEmpty : Boolean get() = size == 0
|
||||
@@ -0,0 +1,301 @@
|
||||
The "99 bottles of beer" song
|
||||
|
||||
99 bottles of beer on the wall, 99 bottles of beer.
|
||||
Take one down, pass it around, 98 bottles of beer on the wall.
|
||||
|
||||
98 bottles of beer on the wall, 98 bottles of beer.
|
||||
Take one down, pass it around, 97 bottles of beer on the wall.
|
||||
|
||||
97 bottles of beer on the wall, 97 bottles of beer.
|
||||
Take one down, pass it around, 96 bottles of beer on the wall.
|
||||
|
||||
96 bottles of beer on the wall, 96 bottles of beer.
|
||||
Take one down, pass it around, 95 bottles of beer on the wall.
|
||||
|
||||
95 bottles of beer on the wall, 95 bottles of beer.
|
||||
Take one down, pass it around, 94 bottles of beer on the wall.
|
||||
|
||||
94 bottles of beer on the wall, 94 bottles of beer.
|
||||
Take one down, pass it around, 93 bottles of beer on the wall.
|
||||
|
||||
93 bottles of beer on the wall, 93 bottles of beer.
|
||||
Take one down, pass it around, 92 bottles of beer on the wall.
|
||||
|
||||
92 bottles of beer on the wall, 92 bottles of beer.
|
||||
Take one down, pass it around, 91 bottles of beer on the wall.
|
||||
|
||||
91 bottles of beer on the wall, 91 bottles of beer.
|
||||
Take one down, pass it around, 90 bottles of beer on the wall.
|
||||
|
||||
90 bottles of beer on the wall, 90 bottles of beer.
|
||||
Take one down, pass it around, 89 bottles of beer on the wall.
|
||||
|
||||
89 bottles of beer on the wall, 89 bottles of beer.
|
||||
Take one down, pass it around, 88 bottles of beer on the wall.
|
||||
|
||||
88 bottles of beer on the wall, 88 bottles of beer.
|
||||
Take one down, pass it around, 87 bottles of beer on the wall.
|
||||
|
||||
87 bottles of beer on the wall, 87 bottles of beer.
|
||||
Take one down, pass it around, 86 bottles of beer on the wall.
|
||||
|
||||
86 bottles of beer on the wall, 86 bottles of beer.
|
||||
Take one down, pass it around, 85 bottles of beer on the wall.
|
||||
|
||||
85 bottles of beer on the wall, 85 bottles of beer.
|
||||
Take one down, pass it around, 84 bottles of beer on the wall.
|
||||
|
||||
84 bottles of beer on the wall, 84 bottles of beer.
|
||||
Take one down, pass it around, 83 bottles of beer on the wall.
|
||||
|
||||
83 bottles of beer on the wall, 83 bottles of beer.
|
||||
Take one down, pass it around, 82 bottles of beer on the wall.
|
||||
|
||||
82 bottles of beer on the wall, 82 bottles of beer.
|
||||
Take one down, pass it around, 81 bottles of beer on the wall.
|
||||
|
||||
81 bottles of beer on the wall, 81 bottles of beer.
|
||||
Take one down, pass it around, 80 bottles of beer on the wall.
|
||||
|
||||
80 bottles of beer on the wall, 80 bottles of beer.
|
||||
Take one down, pass it around, 79 bottles of beer on the wall.
|
||||
|
||||
79 bottles of beer on the wall, 79 bottles of beer.
|
||||
Take one down, pass it around, 78 bottles of beer on the wall.
|
||||
|
||||
78 bottles of beer on the wall, 78 bottles of beer.
|
||||
Take one down, pass it around, 77 bottles of beer on the wall.
|
||||
|
||||
77 bottles of beer on the wall, 77 bottles of beer.
|
||||
Take one down, pass it around, 76 bottles of beer on the wall.
|
||||
|
||||
76 bottles of beer on the wall, 76 bottles of beer.
|
||||
Take one down, pass it around, 75 bottles of beer on the wall.
|
||||
|
||||
75 bottles of beer on the wall, 75 bottles of beer.
|
||||
Take one down, pass it around, 74 bottles of beer on the wall.
|
||||
|
||||
74 bottles of beer on the wall, 74 bottles of beer.
|
||||
Take one down, pass it around, 73 bottles of beer on the wall.
|
||||
|
||||
73 bottles of beer on the wall, 73 bottles of beer.
|
||||
Take one down, pass it around, 72 bottles of beer on the wall.
|
||||
|
||||
72 bottles of beer on the wall, 72 bottles of beer.
|
||||
Take one down, pass it around, 71 bottles of beer on the wall.
|
||||
|
||||
71 bottles of beer on the wall, 71 bottles of beer.
|
||||
Take one down, pass it around, 70 bottles of beer on the wall.
|
||||
|
||||
70 bottles of beer on the wall, 70 bottles of beer.
|
||||
Take one down, pass it around, 69 bottles of beer on the wall.
|
||||
|
||||
69 bottles of beer on the wall, 69 bottles of beer.
|
||||
Take one down, pass it around, 68 bottles of beer on the wall.
|
||||
|
||||
68 bottles of beer on the wall, 68 bottles of beer.
|
||||
Take one down, pass it around, 67 bottles of beer on the wall.
|
||||
|
||||
67 bottles of beer on the wall, 67 bottles of beer.
|
||||
Take one down, pass it around, 66 bottles of beer on the wall.
|
||||
|
||||
66 bottles of beer on the wall, 66 bottles of beer.
|
||||
Take one down, pass it around, 65 bottles of beer on the wall.
|
||||
|
||||
65 bottles of beer on the wall, 65 bottles of beer.
|
||||
Take one down, pass it around, 64 bottles of beer on the wall.
|
||||
|
||||
64 bottles of beer on the wall, 64 bottles of beer.
|
||||
Take one down, pass it around, 63 bottles of beer on the wall.
|
||||
|
||||
63 bottles of beer on the wall, 63 bottles of beer.
|
||||
Take one down, pass it around, 62 bottles of beer on the wall.
|
||||
|
||||
62 bottles of beer on the wall, 62 bottles of beer.
|
||||
Take one down, pass it around, 61 bottles of beer on the wall.
|
||||
|
||||
61 bottles of beer on the wall, 61 bottles of beer.
|
||||
Take one down, pass it around, 60 bottles of beer on the wall.
|
||||
|
||||
60 bottles of beer on the wall, 60 bottles of beer.
|
||||
Take one down, pass it around, 59 bottles of beer on the wall.
|
||||
|
||||
59 bottles of beer on the wall, 59 bottles of beer.
|
||||
Take one down, pass it around, 58 bottles of beer on the wall.
|
||||
|
||||
58 bottles of beer on the wall, 58 bottles of beer.
|
||||
Take one down, pass it around, 57 bottles of beer on the wall.
|
||||
|
||||
57 bottles of beer on the wall, 57 bottles of beer.
|
||||
Take one down, pass it around, 56 bottles of beer on the wall.
|
||||
|
||||
56 bottles of beer on the wall, 56 bottles of beer.
|
||||
Take one down, pass it around, 55 bottles of beer on the wall.
|
||||
|
||||
55 bottles of beer on the wall, 55 bottles of beer.
|
||||
Take one down, pass it around, 54 bottles of beer on the wall.
|
||||
|
||||
54 bottles of beer on the wall, 54 bottles of beer.
|
||||
Take one down, pass it around, 53 bottles of beer on the wall.
|
||||
|
||||
53 bottles of beer on the wall, 53 bottles of beer.
|
||||
Take one down, pass it around, 52 bottles of beer on the wall.
|
||||
|
||||
52 bottles of beer on the wall, 52 bottles of beer.
|
||||
Take one down, pass it around, 51 bottles of beer on the wall.
|
||||
|
||||
51 bottles of beer on the wall, 51 bottles of beer.
|
||||
Take one down, pass it around, 50 bottles of beer on the wall.
|
||||
|
||||
50 bottles of beer on the wall, 50 bottles of beer.
|
||||
Take one down, pass it around, 49 bottles of beer on the wall.
|
||||
|
||||
49 bottles of beer on the wall, 49 bottles of beer.
|
||||
Take one down, pass it around, 48 bottles of beer on the wall.
|
||||
|
||||
48 bottles of beer on the wall, 48 bottles of beer.
|
||||
Take one down, pass it around, 47 bottles of beer on the wall.
|
||||
|
||||
47 bottles of beer on the wall, 47 bottles of beer.
|
||||
Take one down, pass it around, 46 bottles of beer on the wall.
|
||||
|
||||
46 bottles of beer on the wall, 46 bottles of beer.
|
||||
Take one down, pass it around, 45 bottles of beer on the wall.
|
||||
|
||||
45 bottles of beer on the wall, 45 bottles of beer.
|
||||
Take one down, pass it around, 44 bottles of beer on the wall.
|
||||
|
||||
44 bottles of beer on the wall, 44 bottles of beer.
|
||||
Take one down, pass it around, 43 bottles of beer on the wall.
|
||||
|
||||
43 bottles of beer on the wall, 43 bottles of beer.
|
||||
Take one down, pass it around, 42 bottles of beer on the wall.
|
||||
|
||||
42 bottles of beer on the wall, 42 bottles of beer.
|
||||
Take one down, pass it around, 41 bottles of beer on the wall.
|
||||
|
||||
41 bottles of beer on the wall, 41 bottles of beer.
|
||||
Take one down, pass it around, 40 bottles of beer on the wall.
|
||||
|
||||
40 bottles of beer on the wall, 40 bottles of beer.
|
||||
Take one down, pass it around, 39 bottles of beer on the wall.
|
||||
|
||||
39 bottles of beer on the wall, 39 bottles of beer.
|
||||
Take one down, pass it around, 38 bottles of beer on the wall.
|
||||
|
||||
38 bottles of beer on the wall, 38 bottles of beer.
|
||||
Take one down, pass it around, 37 bottles of beer on the wall.
|
||||
|
||||
37 bottles of beer on the wall, 37 bottles of beer.
|
||||
Take one down, pass it around, 36 bottles of beer on the wall.
|
||||
|
||||
36 bottles of beer on the wall, 36 bottles of beer.
|
||||
Take one down, pass it around, 35 bottles of beer on the wall.
|
||||
|
||||
35 bottles of beer on the wall, 35 bottles of beer.
|
||||
Take one down, pass it around, 34 bottles of beer on the wall.
|
||||
|
||||
34 bottles of beer on the wall, 34 bottles of beer.
|
||||
Take one down, pass it around, 33 bottles of beer on the wall.
|
||||
|
||||
33 bottles of beer on the wall, 33 bottles of beer.
|
||||
Take one down, pass it around, 32 bottles of beer on the wall.
|
||||
|
||||
32 bottles of beer on the wall, 32 bottles of beer.
|
||||
Take one down, pass it around, 31 bottles of beer on the wall.
|
||||
|
||||
31 bottles of beer on the wall, 31 bottles of beer.
|
||||
Take one down, pass it around, 30 bottles of beer on the wall.
|
||||
|
||||
30 bottles of beer on the wall, 30 bottles of beer.
|
||||
Take one down, pass it around, 29 bottles of beer on the wall.
|
||||
|
||||
29 bottles of beer on the wall, 29 bottles of beer.
|
||||
Take one down, pass it around, 28 bottles of beer on the wall.
|
||||
|
||||
28 bottles of beer on the wall, 28 bottles of beer.
|
||||
Take one down, pass it around, 27 bottles of beer on the wall.
|
||||
|
||||
27 bottles of beer on the wall, 27 bottles of beer.
|
||||
Take one down, pass it around, 26 bottles of beer on the wall.
|
||||
|
||||
26 bottles of beer on the wall, 26 bottles of beer.
|
||||
Take one down, pass it around, 25 bottles of beer on the wall.
|
||||
|
||||
25 bottles of beer on the wall, 25 bottles of beer.
|
||||
Take one down, pass it around, 24 bottles of beer on the wall.
|
||||
|
||||
24 bottles of beer on the wall, 24 bottles of beer.
|
||||
Take one down, pass it around, 23 bottles of beer on the wall.
|
||||
|
||||
23 bottles of beer on the wall, 23 bottles of beer.
|
||||
Take one down, pass it around, 22 bottles of beer on the wall.
|
||||
|
||||
22 bottles of beer on the wall, 22 bottles of beer.
|
||||
Take one down, pass it around, 21 bottles of beer on the wall.
|
||||
|
||||
21 bottles of beer on the wall, 21 bottles of beer.
|
||||
Take one down, pass it around, 20 bottles of beer on the wall.
|
||||
|
||||
20 bottles of beer on the wall, 20 bottles of beer.
|
||||
Take one down, pass it around, 19 bottles of beer on the wall.
|
||||
|
||||
19 bottles of beer on the wall, 19 bottles of beer.
|
||||
Take one down, pass it around, 18 bottles of beer on the wall.
|
||||
|
||||
18 bottles of beer on the wall, 18 bottles of beer.
|
||||
Take one down, pass it around, 17 bottles of beer on the wall.
|
||||
|
||||
17 bottles of beer on the wall, 17 bottles of beer.
|
||||
Take one down, pass it around, 16 bottles of beer on the wall.
|
||||
|
||||
16 bottles of beer on the wall, 16 bottles of beer.
|
||||
Take one down, pass it around, 15 bottles of beer on the wall.
|
||||
|
||||
15 bottles of beer on the wall, 15 bottles of beer.
|
||||
Take one down, pass it around, 14 bottles of beer on the wall.
|
||||
|
||||
14 bottles of beer on the wall, 14 bottles of beer.
|
||||
Take one down, pass it around, 13 bottles of beer on the wall.
|
||||
|
||||
13 bottles of beer on the wall, 13 bottles of beer.
|
||||
Take one down, pass it around, 12 bottles of beer on the wall.
|
||||
|
||||
12 bottles of beer on the wall, 12 bottles of beer.
|
||||
Take one down, pass it around, 11 bottles of beer on the wall.
|
||||
|
||||
11 bottles of beer on the wall, 11 bottles of beer.
|
||||
Take one down, pass it around, 10 bottles of beer on the wall.
|
||||
|
||||
10 bottles of beer on the wall, 10 bottles of beer.
|
||||
Take one down, pass it around, 9 bottles of beer on the wall.
|
||||
|
||||
9 bottles of beer on the wall, 9 bottles of beer.
|
||||
Take one down, pass it around, 8 bottles of beer on the wall.
|
||||
|
||||
8 bottles of beer on the wall, 8 bottles of beer.
|
||||
Take one down, pass it around, 7 bottles of beer on the wall.
|
||||
|
||||
7 bottles of beer on the wall, 7 bottles of beer.
|
||||
Take one down, pass it around, 6 bottles of beer on the wall.
|
||||
|
||||
6 bottles of beer on the wall, 6 bottles of beer.
|
||||
Take one down, pass it around, 5 bottles of beer on the wall.
|
||||
|
||||
5 bottles of beer on the wall, 5 bottles of beer.
|
||||
Take one down, pass it around, 4 bottles of beer on the wall.
|
||||
|
||||
4 bottles of beer on the wall, 4 bottles of beer.
|
||||
Take one down, pass it around, 3 bottles of beer on the wall.
|
||||
|
||||
3 bottles of beer on the wall, 3 bottles of beer.
|
||||
Take one down, pass it around, 2 bottles of beer on the wall.
|
||||
|
||||
2 bottles of beer on the wall, 2 bottles of beer.
|
||||
Take one down, pass it around, 1 bottle of beer on the wall.
|
||||
|
||||
1 bottle of beer on the wall, 1 bottle of beer.
|
||||
Take one down, pass it around, no more bottles of beer on the wall.
|
||||
|
||||
No more bottles of beer on the wall, no more bottles of beer.
|
||||
Go to the store and buy some more, 99 bottles of beer on the wall.
|
||||
Reference in New Issue
Block a user