diff --git a/js/src/com/google/dart/compiler/util/AstUtil.java b/js/src/com/google/dart/compiler/util/AstUtil.java
index c47a04abcfd..a130ab44be8 100644
--- a/js/src/com/google/dart/compiler/util/AstUtil.java
+++ b/js/src/com/google/dart/compiler/util/AstUtil.java
@@ -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);
diff --git a/translator/src/org/jetbrains/k2js/K2JSTranslator.java b/translator/src/org/jetbrains/k2js/K2JSTranslator.java
index 41c01799e7a..41e5db39ab2 100644
--- a/translator/src/org/jetbrains/k2js/K2JSTranslator.java
+++ b/translator/src/org/jetbrains/k2js/K2JSTranslator.java
@@ -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 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 getJsSupportStdLib() {
+ List libFiles = new ArrayList();
+ 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 files = getJsSupportStdLib();
+ files.add(psiFile);
+ bindingContext = AnalyzerFacade.analyzeFilesWithJavaIntegration(psiFile.getProject(), files, new Predicate() {
+ @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);
diff --git a/translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java b/translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java
index e343bd8794d..b92bb4f2418 100644
--- a/translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java
+++ b/translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java
@@ -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.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, "", "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.lang.Integer";
- standardClasses.declareStandardTopLevelObject(integerFQName, "Integer");
- declareMethods(standardClasses, integerFQName, "parseInt");
- }
-
- private static void declareJavaSystem(@NotNull StandardClasses standardClasses) {
- String systemFQName = ".java.lang.System";
- standardClasses.declareStandardTopLevelObject(systemFQName, "System");
- declareMethods(standardClasses, systemFQName, "out");
- String printStreamFQName = ".java.io.PrintStream";
- //TODO:
- standardClasses.declareStandardTopLevelObject(printStreamFQName, "ErrorName");
- declareMethods(standardClasses, printStreamFQName, "print", "println");
- }
private static void declareJavaArrayList(@NotNull StandardClasses standardClasses) {
- String arrayListFQName = ".java.util.ArrayList";
+ String arrayListFQName = "java.util.ArrayList";
standardClasses.declareStandardTopLevelObject(arrayListFQName, "ArrayList");
standardClasses.declareStandardInnerDeclaration(arrayListFQName, "", "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);
+
}
}
diff --git a/translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsics.java b/translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsics.java
index 9a0c4594487..cf5fca0da83 100644
--- a/translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsics.java
+++ b/translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsics.java
@@ -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) {
diff --git a/translator/src/org/jetbrains/k2js/translate/intrinsic/array/IntrinsicArrayUtils.java b/translator/src/org/jetbrains/k2js/translate/intrinsic/array/IntrinsicArrayUtils.java
index 620d2ef7dff..dab49e8ef57 100644
--- a/translator/src/org/jetbrains/k2js/translate/intrinsic/array/IntrinsicArrayUtils.java
+++ b/translator/src/org/jetbrains/k2js/translate/intrinsic/array/IntrinsicArrayUtils.java
@@ -36,6 +36,6 @@ public final class IntrinsicArrayUtils {
@NotNull
private static JsExpression throwOutOfBoundsException() {
//TODO: think about exception
- return new JsThisRef();
+ return AstUtil.newQualifiedNameRef("ErrorName");
}
}
diff --git a/translator/src/org/jetbrains/k2js/translate/intrinsic/string/LengthIntrinsic.java b/translator/src/org/jetbrains/k2js/translate/intrinsic/string/LengthIntrinsic.java
new file mode 100644
index 00000000000..5e731d7d76a
--- /dev/null
+++ b/translator/src/org/jetbrains/k2js/translate/intrinsic/string/LengthIntrinsic.java
@@ -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 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;
+ }
+}
\ No newline at end of file
diff --git a/translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java b/translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java
index 883934d8acd..a4bbf3bedab 100644
--- a/translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java
+++ b/translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java
@@ -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.emptyList(), functionDescriptor, context)).translate();
+ return translate(receiver, Collections.emptyList(), functionDescriptor, context);
+ }
+
+ @NotNull
+ public static JsExpression translate(@Nullable JsExpression receiver, @NotNull List arguments,
+ @NotNull CallableDescriptor functionDescriptor,
+ @NotNull TranslationContext context) {
+ return (new CallTranslator(receiver, arguments, functionDescriptor, context)).translate();
}
@NotNull
diff --git a/translator/src/org/jetbrains/k2js/translate/reference/PropertyAccessTranslator.java b/translator/src/org/jetbrains/k2js/translate/reference/PropertyAccessTranslator.java
index 9134489f70a..104fe0c5bb2 100644
--- a/translator/src/org/jetbrains/k2js/translate/reference/PropertyAccessTranslator.java
+++ b/translator/src/org/jetbrains/k2js/translate/reference/PropertyAccessTranslator.java
@@ -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();
diff --git a/translator/test/org/jetbrains/k2js/test/FunctionTest.java b/translator/test/org/jetbrains/k2js/test/FunctionTest.java
index 9882a4ea42c..133a6e1fa65 100644
--- a/translator/test/org/jetbrains/k2js/test/FunctionTest.java
+++ b/translator/test/org/jetbrains/k2js/test/FunctionTest.java
@@ -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
diff --git a/translator/test/org/jetbrains/k2js/test/MiscTest.java b/translator/test/org/jetbrains/k2js/test/MiscTest.java
index 3ab5c7b0ef8..105ccd357e5 100644
--- a/translator/test/org/jetbrains/k2js/test/MiscTest.java
+++ b/translator/test/org/jetbrains/k2js/test/MiscTest.java
@@ -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");
- }
}
diff --git a/translator/test/org/jetbrains/k2js/test/OperationTest.java b/translator/test/org/jetbrains/k2js/test/OperationTest.java
index 967003ba948..af8225b1a0f 100644
--- a/translator/test/org/jetbrains/k2js/test/OperationTest.java
+++ b/translator/test/org/jetbrains/k2js/test/OperationTest.java
@@ -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
diff --git a/translator/test/org/jetbrains/k2js/test/SystemTest.java b/translator/test/org/jetbrains/k2js/test/SystemTest.java
deleted file mode 100644
index c0c5c02e77a..00000000000
--- a/translator/test/org/jetbrains/k2js/test/SystemTest.java
+++ /dev/null
@@ -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");
- }
-}
diff --git a/translator/test/org/jetbrains/k2js/test/TranslationTest.java b/translator/test/org/jetbrains/k2js/test/TranslationTest.java
index a27a5112d3f..27c5e631b17 100644
--- a/translator/test/org/jetbrains/k2js/test/TranslationTest.java
+++ b/translator/test/org/jetbrains/k2js/test/TranslationTest.java
@@ -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();
+ }
+ }
+
+
}
diff --git a/translator/test/org/jetbrains/k2js/test/WebDemoExamplesTest.java b/translator/test/org/jetbrains/k2js/test/WebDemoExamples1Test.java
similarity index 94%
rename from translator/test/org/jetbrains/k2js/test/WebDemoExamplesTest.java
rename to translator/test/org/jetbrains/k2js/test/WebDemoExamples1Test.java
index 9b36d134581..a4162231c21 100644
--- a/translator/test/org/jetbrains/k2js/test/WebDemoExamplesTest.java
+++ b/translator/test/org/jetbrains/k2js/test/WebDemoExamples1Test.java
@@ -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() {
diff --git a/translator/test/org/jetbrains/k2js/test/WebDemoExamples2Test.java b/translator/test/org/jetbrains/k2js/test/WebDemoExamples2Test.java
new file mode 100644
index 00000000000..c6c52beee82
--- /dev/null
+++ b/translator/test/org/jetbrains/k2js/test/WebDemoExamples2Test.java
@@ -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", "");
+ }
+
+
+}
diff --git a/translator/testFiles/examples/sortedTests/unsupported/basicproperty.jet b/translator/testFiles/examples/sortedTests/unsupported/basicproperty.jet
index 196ed3f40b0..ae1cfa5618b 100644
--- a/translator/testFiles/examples/sortedTests/unsupported/basicproperty.jet
+++ b/translator/testFiles/examples/sortedTests/unsupported/basicproperty.jet
@@ -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";
}
\ No newline at end of file
diff --git a/translator/testFiles/examples/sortedTests/unsupported/traitproperty.jet b/translator/testFiles/examples/sortedTests/unsupported/traitproperty.jet
index 962f71c5dc9..715d8d73d8b 100644
--- a/translator/testFiles/examples/sortedTests/unsupported/traitproperty.jet
+++ b/translator/testFiles/examples/sortedTests/unsupported/traitproperty.jet
@@ -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";
}
\ No newline at end of file
diff --git a/translator/testFiles/expression/function/cases/KT-921.kt b/translator/testFiles/expression/function/cases/KT-921.kt
index 05b388369f7..7c41a0fc0c0 100644
--- a/translator/testFiles/expression/function/cases/KT-921.kt
+++ b/translator/testFiles/expression/function/cases/KT-921.kt
@@ -46,8 +46,8 @@ fun lifetime(body: (Lifetime)->Unit)
fun Dump(items:ArrayList)
{
for(item in items)
- System.out?.print(item.toString() + ", ")
- System.out?.println()
+ print(item.toString() + ", ")
+ println()
}
fun main(args:Array)
diff --git a/translator/testFiles/expression/function/cases/closureWithParameter.jet b/translator/testFiles/expression/function/cases/closureWithParameter.kt
similarity index 100%
rename from translator/testFiles/expression/function/cases/closureWithParameter.jet
rename to translator/testFiles/expression/function/cases/closureWithParameter.kt
diff --git a/translator/testFiles/expression/function/cases/enclosingThis.jet b/translator/testFiles/expression/function/cases/enclosingThis.kt
similarity index 100%
rename from translator/testFiles/expression/function/cases/enclosingThis.jet
rename to translator/testFiles/expression/function/cases/enclosingThis.kt
diff --git a/translator/testFiles/expression/misc/cases/KT-962.kt b/translator/testFiles/expression/misc/cases/KT-962.kt
index 9f435bdf9a4..c922a8c4136 100644
--- a/translator/testFiles/expression/misc/cases/KT-962.kt
+++ b/translator/testFiles/expression/misc/cases/KT-962.kt
@@ -1,5 +1,7 @@
+iimport
+
fun stdout(): java.io.PrintStream? {
- System.out?.println("stdout")
+ println("stdout")
return System.out
}
diff --git a/translator/testFiles/expression/misc/cases/intRange.kt b/translator/testFiles/expression/misc/cases/intRange.kt
index 668b26ae1ea..73d578db692 100644
--- a/translator/testFiles/expression/misc/cases/intRange.kt
+++ b/translator/testFiles/expression/misc/cases/intRange.kt
@@ -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) {
- System.out?.println(box())
+ println(box())
}
\ No newline at end of file
diff --git a/translator/testFiles/expression/operation/cases/assign.jet b/translator/testFiles/expression/operation/cases/assign.kt
similarity index 100%
rename from translator/testFiles/expression/operation/cases/assign.jet
rename to translator/testFiles/expression/operation/cases/assign.kt
diff --git a/translator/testFiles/java/system/cases/print.kt b/translator/testFiles/java/system/cases/print.kt
deleted file mode 100644
index 4913966a4d2..00000000000
--- a/translator/testFiles/java/system/cases/print.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-fun main(args : Array) {
- System.out?.print("Hello, world!");
-}
diff --git a/translator/testFiles/java/system/cases/println.kt b/translator/testFiles/java/system/cases/println.kt
deleted file mode 100644
index 3881178af15..00000000000
--- a/translator/testFiles/java/system/cases/println.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-fun main(args : Array) {
- System.out?.println("Hello, world!");
- System.out?.println(3);
- System.out?.println();
-}
diff --git a/translator/testFiles/kotlin_lib.js b/translator/testFiles/kotlin_lib.js
index e62cd2728a6..03a2c5a98bf 100644
--- a/translator/testFiles/kotlin_lib.js
+++ b/translator/testFiles/kotlin_lib.js
@@ -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();
}
});
diff --git a/translator/testFiles/range/cases/explicitRange.kt b/translator/testFiles/range/cases/explicitRange.kt
index 0e9b843d3d2..3c8595027e3 100644
--- a/translator/testFiles/range/cases/explicitRange.kt
+++ b/translator/testFiles/range/cases/explicitRange.kt
@@ -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;
diff --git a/translator/testFiles/range/cases/intInRange.kt b/translator/testFiles/range/cases/intInRange.kt
index 46f7c542016..95959d09eb2 100644
--- a/translator/testFiles/range/cases/intInRange.kt
+++ b/translator/testFiles/range/cases/intInRange.kt
@@ -1,5 +1,7 @@
package foo
+
+
fun box() : Boolean {
if (1 in -2..0) return false;
diff --git a/translator/testFiles/range/cases/rangeSugarSyntax.kt b/translator/testFiles/range/cases/rangeSugarSyntax.kt
index 8ea37e12359..d300924fe91 100644
--- a/translator/testFiles/range/cases/rangeSugarSyntax.kt
+++ b/translator/testFiles/range/cases/rangeSugarSyntax.kt
@@ -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;
diff --git a/translator/testFiles/webDemoExamples/cases/forLoop.kt b/translator/testFiles/webDemoExamples/cases/forLoop.kt
deleted file mode 100644
index 5c8cf6ce528..00000000000
--- a/translator/testFiles/webDemoExamples/cases/forLoop.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-fun main(args : Array) {
- for (arg in args)
- System.out?.println(arg)
-
- // or
- System.out?.println()
- for (i in args.indices)
- System.out?.println(args[i])
-}
diff --git a/translator/testFiles/webDemoExamples/cases/ifAsExpression.kt b/translator/testFiles/webDemoExamples/cases/ifAsExpression.kt
deleted file mode 100644
index bb8b9c0573c..00000000000
--- a/translator/testFiles/webDemoExamples/cases/ifAsExpression.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-fun main(args : Array) {
- System.out?.println(max(Integer.parseInt(args[0]), Integer.parseInt(args[1])))
-}
-
-fun max(a : Int, b : Int) = if (a > b) a else b
\ No newline at end of file
diff --git a/translator/testFiles/webDemoExamples/cases/isCheck.kt b/translator/testFiles/webDemoExamples/cases/isCheck.kt
deleted file mode 100644
index ace651c385c..00000000000
--- a/translator/testFiles/webDemoExamples/cases/isCheck.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-fun main(args : Array) {
- 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
-}
\ No newline at end of file
diff --git a/translator/testFiles/webDemoExamples/cases/multiLanguageHello.kt b/translator/testFiles/webDemoExamples/cases/multiLanguageHello.kt
deleted file mode 100644
index 0038a5e12c0..00000000000
--- a/translator/testFiles/webDemoExamples/cases/multiLanguageHello.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-fun main(args : Array) {
- 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"
- })
-}
diff --git a/translator/testFiles/webDemoExamples/cases/nullChecks.kt b/translator/testFiles/webDemoExamples/cases/nullChecks.kt
deleted file mode 100644
index ebfac5371a5..00000000000
--- a/translator/testFiles/webDemoExamples/cases/nullChecks.kt
+++ /dev/null
@@ -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) {
- 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
- }
- }
-}
diff --git a/translator/testFiles/webDemoExamples/cases/objectOrientedHello.kt b/translator/testFiles/webDemoExamples/cases/objectOrientedHello.kt
deleted file mode 100644
index b50d54bbb9d..00000000000
--- a/translator/testFiles/webDemoExamples/cases/objectOrientedHello.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-class Greeter(name : String) {
- val name = name
- fun greet() {
- System.out?.println("Hello, ${name}!");
- }
-}
-
-fun main(args : Array) {
- Greeter(args[0]).greet()
-}
\ No newline at end of file
diff --git a/translator/testFiles/webDemoExamples/cases/patternMatching.kt b/translator/testFiles/webDemoExamples/cases/patternMatching.kt
deleted file mode 100644
index 5dd0be84862..00000000000
--- a/translator/testFiles/webDemoExamples/cases/patternMatching.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-fun main(args : Array) {
- 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() {
-}
diff --git a/translator/testFiles/webDemoExamples/cases/printArg.kt b/translator/testFiles/webDemoExamples/cases/printArg.kt
deleted file mode 100644
index 0300a93901e..00000000000
--- a/translator/testFiles/webDemoExamples/cases/printArg.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-fun main(args : Array) {
- System.out?.print(args[0]);
-}
diff --git a/translator/testFiles/webDemoExamples/cases/ranges.kt b/translator/testFiles/webDemoExamples/cases/ranges.kt
deleted file mode 100644
index e64fc693342..00000000000
--- a/translator/testFiles/webDemoExamples/cases/ranges.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-import java.util.ArrayList;
-
-fun main(args : Array) {
- 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();
-
- 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")
-}
-
-
diff --git a/translator/testFiles/webDemoExamples/cases/whileLoop.kt b/translator/testFiles/webDemoExamples/cases/whileLoop.kt
deleted file mode 100644
index 5ef65053397..00000000000
--- a/translator/testFiles/webDemoExamples/cases/whileLoop.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-fun main(args : Array) {
- var i = 0
- while (i < args.size)
- System.out?.println(args[i++])
-}
diff --git a/translator/testFiles/webDemoExamples2/cases/bottles.kt b/translator/testFiles/webDemoExamples2/cases/bottles.kt
new file mode 100644
index 00000000000..f6f96395c99
--- /dev/null
+++ b/translator/testFiles/webDemoExamples2/cases/bottles.kt
@@ -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) {
+ 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, but does not sit inside the class Array
+val Array.isEmpty : Boolean get() = size == 0
diff --git a/translator/testFiles/webDemoExamples2/expected/bottles.out b/translator/testFiles/webDemoExamples2/expected/bottles.out
new file mode 100644
index 00000000000..e7b140a5f40
--- /dev/null
+++ b/translator/testFiles/webDemoExamples2/expected/bottles.out
@@ -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.
\ No newline at end of file