diff --git a/il65/src/compile.sh b/il65/src/compile.sh new file mode 100644 index 000000000..69fff3713 --- /dev/null +++ b/il65/src/compile.sh @@ -0,0 +1,5 @@ +#!/bin/sh +mkdir -p compiled_java +javac -d compiled_java -cp ../antlr/lib/antlr-runtime-4.7.1.jar $(find . -name \*.java) +jar cf parser.jar -C compiled_java il65 +kotlinc -d il65_kotlin.jar -include-runtime -cp ../antlr/lib/antlr-runtime-4.7.1.jar:parser.jar il65 diff --git a/il65/src/il65/Main.kt b/il65/src/il65/Main.kt index 94ddd93e8..dc1dd4ba2 100644 --- a/il65/src/il65/Main.kt +++ b/il65/src/il65/Main.kt @@ -1,6 +1,7 @@ package il65 import il65.ast.* +import il65.optimizing.optimize import il65.parser.il65Lexer import il65.parser.il65Parser import org.antlr.v4.runtime.CharStreams @@ -87,10 +88,10 @@ fun discoverImportedModule(name: String, importedFrom: Path, position: Position? val fileName = name + ".ill" val locations = mutableListOf(Paths.get(importedFrom.parent.toString())) - val propPath = System.getProperty("il65.libpath") + val propPath = System.getProperty("il65.libdir") if(propPath!=null) locations.add(Paths.get(propPath)) - val envPath = System.getenv("IL65_LIBPATH") + val envPath = System.getenv("IL65_LIBDIR") if(envPath!=null) locations.add(Paths.get(envPath)) locations.add(Paths.get(Paths.get("").toAbsolutePath().toString(), "lib65")) @@ -113,7 +114,7 @@ fun executeImportDirective(import: Directive, importedFrom: Path): Module? { val modulePath = discoverImportedModule(moduleName, importedFrom, import.position) val importedModule = loadModule(modulePath) - importedModule.checkImportValid() + importedModule.checkImportedValid() return importedModule } diff --git a/il65/src/il65/ast/AstChecker.kt b/il65/src/il65/ast/AstChecker.kt index 01a18fb37..e09741e01 100644 --- a/il65/src/il65/ast/AstChecker.kt +++ b/il65/src/il65/ast/AstChecker.kt @@ -2,6 +2,9 @@ package il65.ast import il65.ParsingFailedError +/** + * General checks on the Ast + */ fun Module.checkValid(globalNamespace: INameScope) { val checker = AstChecker(globalNamespace) diff --git a/il65/src/il65/ast/ImportedAstChecker.kt b/il65/src/il65/ast/ImportedAstChecker.kt index c985c6a60..2427cb1b9 100644 --- a/il65/src/il65/ast/ImportedAstChecker.kt +++ b/il65/src/il65/ast/ImportedAstChecker.kt @@ -2,8 +2,11 @@ package il65.ast import il65.ParsingFailedError +/** + * Checks that are specific for imported modules. + */ -fun Module.checkImportValid() { +fun Module.checkImportedValid() { val checker = ImportedAstChecker() this.process(checker) val result = checker.result() @@ -11,7 +14,7 @@ fun Module.checkImportValid() { it.printError() } if(result.isNotEmpty()) - throw ParsingFailedError("There are ${result.size} errors in module '$name'.") + throw ParsingFailedError("There are ${result.size} errors in imported module '$name'.") } @@ -22,6 +25,9 @@ class ImportedAstChecker : IAstProcessor { return checkResult } + /** + * Module check: most global directives don't apply for imported modules + */ override fun process(module: Module) { super.process(module) val newStatements : MutableList = mutableListOf() diff --git a/il65/src/il65/functions/BuiltinFunctions.kt b/il65/src/il65/functions/BuiltinFunctions.kt index 360442533..756139027 100644 --- a/il65/src/il65/functions/BuiltinFunctions.kt +++ b/il65/src/il65/functions/BuiltinFunctions.kt @@ -48,18 +48,41 @@ private fun twoDoubleArg(args: List, namespace: INameScope, functio throw UnsupportedOperationException("built-in function requires two floating point values as argument") } -fun builtin_round(args: List, namespace: INameScope): LiteralValue = oneDoubleArgOutputInt(args, namespace) { it -> Math.round(it).toInt() } -fun builtin_sin(args: List, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::sin) -fun builtin_cos(args: List, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::cos) -fun builtin_acos(args: List, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::acos) -fun builtin_asin(args: List, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::asin) -fun builtin_tan(args: List, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::tan) -fun builtin_atan(args: List, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::atan) -fun builtin_log(args: List, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::log) -fun builtin_log10(args: List, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::log10) -fun builtin_sqrt(args: List, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::sqrt) -fun builtin_rad(args: List, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::toRadians) -fun builtin_deg(args: List, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::toDegrees) +fun builtin_round(args: List, namespace: INameScope): LiteralValue + = oneDoubleArgOutputInt(args, namespace) { it -> Math.round(it).toInt() } + +fun builtin_sin(args: List, namespace: INameScope): LiteralValue + = oneDoubleArg(args, namespace, Math::sin) + +fun builtin_cos(args: List, namespace: INameScope): LiteralValue + = oneDoubleArg(args, namespace, Math::cos) + +fun builtin_acos(args: List, namespace: INameScope): LiteralValue + = oneDoubleArg(args, namespace, Math::acos) + +fun builtin_asin(args: List, namespace: INameScope): LiteralValue + = oneDoubleArg(args, namespace, Math::asin) + +fun builtin_tan(args: List, namespace: INameScope): LiteralValue + = oneDoubleArg(args, namespace, Math::tan) + +fun builtin_atan(args: List, namespace: INameScope): LiteralValue + = oneDoubleArg(args, namespace, Math::atan) + +fun builtin_log(args: List, namespace: INameScope): LiteralValue + = oneDoubleArg(args, namespace, Math::log) + +fun builtin_log10(args: List, namespace: INameScope): LiteralValue + = oneDoubleArg(args, namespace, Math::log10) + +fun builtin_sqrt(args: List, namespace: INameScope): LiteralValue + = oneDoubleArg(args, namespace, Math::sqrt) + +fun builtin_rad(args: List, namespace: INameScope): LiteralValue + = oneDoubleArg(args, namespace, Math::toRadians) + +fun builtin_deg(args: List, namespace: INameScope): LiteralValue + = oneDoubleArg(args, namespace, Math::toDegrees) fun builtin_abs(args: List, namespace: INameScope): LiteralValue { if(args.size!=1) diff --git a/il65/src/il65/ast/AstOptimizer.kt b/il65/src/il65/optimizing/ExpressionOptimizer.kt similarity index 91% rename from il65/src/il65/ast/AstOptimizer.kt rename to il65/src/il65/optimizing/ExpressionOptimizer.kt index d2e6d03d0..3f9cd1e61 100644 --- a/il65/src/il65/ast/AstOptimizer.kt +++ b/il65/src/il65/optimizing/ExpressionOptimizer.kt @@ -1,10 +1,11 @@ -package il65.ast +package il65.optimizing +import il65.ast.* import kotlin.math.pow fun Module.optimize(globalNamespace: INameScope) { - val optimizer = AstOptimizer(globalNamespace) + val optimizer = ExpressionOptimizer(globalNamespace) this.process(optimizer) if(optimizer.optimizationsDone==0) println("[${this.name}] 0 optimizations performed") @@ -18,7 +19,7 @@ fun Module.optimize(globalNamespace: INameScope) { } -class AstOptimizer(private val globalNamespace: INameScope) : IAstProcessor { +class ExpressionOptimizer(private val globalNamespace: INameScope) : IAstProcessor { var optimizationsDone: Int = 0 private set @@ -27,7 +28,7 @@ class AstOptimizer(private val globalNamespace: INameScope) : IAstProcessor { } /** - * some identifiers can be replaced with the constant value they refer to + * replace identifiers that refer to const value, with the value itself */ override fun process(identifier: Identifier): IExpression { return identifier.constValue(globalNamespace) ?: identifier @@ -141,7 +142,7 @@ class ConstExprEvaluator { private fun comparenotequal(left: LiteralValue, right: LiteralValue): LiteralValue { val leq = compareequal(left, right) - val litval = LiteralValue(intvalue = if(leq.intvalue==1) 0 else 1) + val litval = LiteralValue(intvalue = if (leq.intvalue == 1) 0 else 1) litval.position = left.position return litval } @@ -161,7 +162,7 @@ class ConstExprEvaluator { right.arrayvalue!=null -> right.arrayvalue else -> throw AstException("missing literal value") } - val litval = LiteralValue(intvalue = if(leftvalue==rightvalue) 1 else 0) + val litval = LiteralValue(intvalue = if (leftvalue == rightvalue) 1 else 0) litval.position = left.position return litval } @@ -214,14 +215,14 @@ class ConstExprEvaluator { private fun comparegreater(left: LiteralValue, right: LiteralValue): LiteralValue { val leq = comparelessequal(left, right) - val litval = LiteralValue(intvalue = if(leq.intvalue==1) 0 else 1) + val litval = LiteralValue(intvalue = if (leq.intvalue == 1) 0 else 1) litval.position = left.position return litval } private fun compareless(left: LiteralValue, right: LiteralValue): LiteralValue { val leq = comparegreaterequal(left, right) - val litval = LiteralValue(intvalue = if(leq.intvalue==1) 0 else 1) + val litval = LiteralValue(intvalue = if (leq.intvalue == 1) 0 else 1) litval.position = left.position return litval } @@ -231,16 +232,16 @@ class ConstExprEvaluator { val litval = when { left.intvalue!=null -> when { right.intvalue!=null -> LiteralValue( - intvalue = if ((left.intvalue!=0).xor(right.intvalue!=0)) 1 else 0) + intvalue = if ((left.intvalue != 0).xor(right.intvalue != 0)) 1 else 0) right.floatvalue!=null -> LiteralValue( - intvalue = if ((left.intvalue!=0).xor(right.floatvalue!=0.0)) 1 else 0) + intvalue = if ((left.intvalue != 0).xor(right.floatvalue != 0.0)) 1 else 0) else -> throw ExpressionException(error) } left.floatvalue!=null -> when { right.intvalue!=null -> LiteralValue( - intvalue = if ((left.floatvalue!=0.0).xor(right.intvalue!=0)) 1 else 0) + intvalue = if ((left.floatvalue != 0.0).xor(right.intvalue != 0)) 1 else 0) right.floatvalue!=null -> LiteralValue( - intvalue = if ((left.floatvalue!=0.0).xor(right.floatvalue!=0.0)) 1 else 0) + intvalue = if ((left.floatvalue != 0.0).xor(right.floatvalue != 0.0)) 1 else 0) else -> throw ExpressionException(error) } else -> throw ExpressionException(error) @@ -254,16 +255,16 @@ class ConstExprEvaluator { val litval = when { left.intvalue!=null -> when { right.intvalue!=null -> LiteralValue( - intvalue = if (left.intvalue!=0 || right.intvalue!=0) 1 else 0) + intvalue = if (left.intvalue != 0 || right.intvalue != 0) 1 else 0) right.floatvalue!=null -> LiteralValue( - intvalue = if (left.intvalue!=0 || right.floatvalue!=0.0) 1 else 0) + intvalue = if (left.intvalue != 0 || right.floatvalue != 0.0) 1 else 0) else -> throw ExpressionException(error) } left.floatvalue!=null -> when { right.intvalue!=null -> LiteralValue( - intvalue = if (left.floatvalue!=0.0 || right.intvalue!=0) 1 else 0) + intvalue = if (left.floatvalue != 0.0 || right.intvalue != 0) 1 else 0) right.floatvalue!=null -> LiteralValue( - intvalue = if (left.floatvalue!=0.0 || right.floatvalue!=0.0) 1 else 0) + intvalue = if (left.floatvalue != 0.0 || right.floatvalue != 0.0) 1 else 0) else -> throw ExpressionException(error) } else -> throw ExpressionException(error) @@ -277,16 +278,16 @@ class ConstExprEvaluator { val litval = when { left.intvalue!=null -> when { right.intvalue!=null -> LiteralValue( - intvalue = if (left.intvalue!=0 && right.intvalue!=0) 1 else 0) + intvalue = if (left.intvalue != 0 && right.intvalue != 0) 1 else 0) right.floatvalue!=null -> LiteralValue( - intvalue = if (left.intvalue!=0 && right.floatvalue!=0.0) 1 else 0) + intvalue = if (left.intvalue != 0 && right.floatvalue != 0.0) 1 else 0) else -> throw ExpressionException(error) } left.floatvalue!=null -> when { right.intvalue!=null -> LiteralValue( - intvalue = if (left.floatvalue!=0.0 && right.intvalue!=0) 1 else 0) + intvalue = if (left.floatvalue != 0.0 && right.intvalue != 0) 1 else 0) right.floatvalue!=null -> LiteralValue( - intvalue = if (left.floatvalue!=0.0 && right.floatvalue!=0.0) 1 else 0) + intvalue = if (left.floatvalue != 0.0 && right.floatvalue != 0.0) 1 else 0) else -> throw ExpressionException(error) } else -> throw ExpressionException(error)