diff --git a/docs/index.papyri b/docs/index.papyri index aab7234..781c002 100644 --- a/docs/index.papyri +++ b/docs/index.papyri @@ -45,7 +45,10 @@ This will create a JAR file in `metis-app/build/libs` that can be run with `java @h2 { 0.3.0 } [ {Fixed upvalues having the wrong value when the function is passed as an argument}, - {Added functions to `list` and `string`} + {Added functions to `list` and `string`}, + {Changed the comment character from `//` to `\#`}, + {Implemented the `**` (power) and `//` (floor division) operators}, + {Changed `__inclrange__` to `__inclRange__` for consistency}, ] @h2 { 0.2.0 } diff --git a/metis-app/src/main/kotlin/io/github/seggan/metis/app/SyntaxHighlighting.kt b/metis-app/src/main/kotlin/io/github/seggan/metis/app/SyntaxHighlighting.kt index 8860479..92bd177 100644 --- a/metis-app/src/main/kotlin/io/github/seggan/metis/app/SyntaxHighlighting.kt +++ b/metis-app/src/main/kotlin/io/github/seggan/metis/app/SyntaxHighlighting.kt @@ -17,9 +17,9 @@ fun highlight(tokens: List): String = createHTML(prettyPrint = false).spa FN, GLOBAL, LET, DO, END, ERROR, EXCEPT, FINALLY, RAISE, IMPORT -> "keyword" - PLUS, MINUS, STAR, SLASH, PERCENT, RANGE, INCLUSIVE_RANGE, ELVIS, QUESTION_MARK, EQUALS, DOUBLE_EQUALS, - NOT_EQUALS, GREATER_THAN, LESS_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN_OR_EQUAL, BAND, BOR, BXOR, SHL, - SHR, SHRU, BNOT + PLUS, MINUS, STAR, DOUBLE_STAR, SLASH, DOUBLE_SLASH, PERCENT, RANGE, INCLUSIVE_RANGE, ELVIS, + QUESTION_MARK, EQUALS, DOUBLE_EQUALS, NOT_EQUALS, GREATER_THAN, LESS_THAN, GREATER_THAN_OR_EQUAL, + LESS_THAN_OR_EQUAL, BAND, BOR, BXOR, SHL, SHR, SHRU, BNOT -> "operator" DOT, COLON, COMMA, SEMICOLON -> "punctuation" diff --git a/metis-lang/src/main/kotlin/io/github/seggan/metis/compilation/Op.kt b/metis-lang/src/main/kotlin/io/github/seggan/metis/compilation/Op.kt index dcaf995..5503141 100644 --- a/metis-lang/src/main/kotlin/io/github/seggan/metis/compilation/Op.kt +++ b/metis-lang/src/main/kotlin/io/github/seggan/metis/compilation/Op.kt @@ -8,10 +8,11 @@ enum class BinOp(internal val generateCode: InsnsBuilder.(List, List, private val source: CodeSource) { ) private fun parseComparison() = parseBinOp( - ::parseIn, mapOf( + ::parseIn, + mapOf( LESS_THAN to BinOp.LESS, LESS_THAN_OR_EQUAL to BinOp.LESS_EQ, GREATER_THAN to BinOp.GREATER, @@ -127,8 +128,13 @@ class Parser(tokens: List, private val source: CodeSource) { ) private fun parseElvis() = parseBinOp(::parseRange, mapOf(ELVIS to BinOp.ELVIS)) - private fun parseRange() = - parseBinOp(::parseBitOr, mapOf(RANGE to BinOp.RANGE, INCLUSIVE_RANGE to BinOp.INCLUSIVE_RANGE)) + private fun parseRange() = parseBinOp( + ::parseBitOr, + mapOf( + RANGE to BinOp.RANGE, + INCLUSIVE_RANGE to BinOp.INCLUSIVE_RANGE + ) + ) private fun parseBitOr() = parseBinOp(::parseBitXor, mapOf(BOR to BinOp.BOR)) private fun parseBitXor() = parseBinOp(::parseBitAnd, mapOf(BXOR to BinOp.BXOR)) @@ -142,9 +148,23 @@ class Parser(tokens: List, private val source: CodeSource) { ) ) - private fun parseAddition() = parseBinOp(::parseMultiplication, mapOf(PLUS to BinOp.PLUS, MINUS to BinOp.MINUS)) - private fun parseMultiplication() = - parseBinOp(::parseUnary, mapOf(STAR to BinOp.TIMES, SLASH to BinOp.DIV, PERCENT to BinOp.MOD)) + private fun parseAddition() = parseBinOp( + ::parseMultiplication, + mapOf( + PLUS to BinOp.PLUS, + MINUS to BinOp.MINUS + ) + ) + + private fun parseMultiplication() = parseBinOp( + ::parseUnary, + mapOf( + STAR to BinOp.TIMES, + SLASH to BinOp.DIV, + DOUBLE_SLASH to BinOp.FLOORDIV, + PERCENT to BinOp.MOD + ) + ) private fun parseUnary(): AstNode.Expression { val op = tryConsume(NOT, MINUS, BNOT) @@ -159,7 +179,16 @@ class Parser(tokens: List, private val source: CodeSource) { }, expr, op.span + expr.span ) } - return parsePostfix() + return parsePower() + } + + // Has to be separate because of right-associativity + private fun parsePower(): AstNode.Expression { + var expr = parsePostfix() + while (tryConsume(DOUBLE_STAR) != null) { + expr = AstNode.BinaryOp(expr, BinOp.POW, parsePower()) + } + return expr } private fun parsePostfix(allowCalls: Boolean = true): AstNode.Expression { diff --git a/metis-lang/src/main/kotlin/io/github/seggan/metis/runtime/intrinsics/ValueInit.kt b/metis-lang/src/main/kotlin/io/github/seggan/metis/runtime/intrinsics/ValueInit.kt index 5841e8d..33cb116 100644 --- a/metis-lang/src/main/kotlin/io/github/seggan/metis/runtime/intrinsics/ValueInit.kt +++ b/metis-lang/src/main/kotlin/io/github/seggan/metis/runtime/intrinsics/ValueInit.kt @@ -123,6 +123,9 @@ internal fun initNumber() = buildTable { table -> table["__div__"] = twoArgFunction(true) { self, other -> Value.Number.of(self.doubleValue() / other.doubleValue()) } + table["__floordiv__"] = twoArgFunction(true) { self, other -> + Value.Number.of((self.doubleValue() / other.doubleValue()).toInt()) + } table["__mod__"] = twoArgFunction(true) { self, other -> Value.Number.of(self.doubleValue() % other.doubleValue()) } diff --git a/metis-lang/src/main/resources/core/list.metis b/metis-lang/src/main/resources/core/list.metis index 8633ee7..7c61bb3 100644 --- a/metis-lang/src/main/resources/core/list.metis +++ b/metis-lang/src/main/resources/core/list.metis @@ -54,7 +54,7 @@ end fn list.sort(self, compare) compare = compare ?: cmp - let pivot = self[len(self) / 2] + let pivot = self[len(self) // 2] let less = list.new() let equal = list.new() let greater = list.new() diff --git a/metis-lang/src/main/resources/core/range.metis b/metis-lang/src/main/resources/core/range.metis index 5a93c90..3fde474 100644 --- a/metis-lang/src/main/resources/core/range.metis +++ b/metis-lang/src/main/resources/core/range.metis @@ -24,6 +24,6 @@ fn range.exclusive(start, stop, step) = withMetatable({ fn range.inclusive(start, stop, step) = range.exclusive(start, stop + step, step) fn number.__range__(self, other) = range.exclusive(self, other, 1) -fn number.__inclrange__(self, other) = range.inclusive(self, other, 1) +fn number.__inclRange__(self, other) = range.inclusive(self, other, 1) fn range.reverse(self) = range.exclusive(self.stop - self.step, self.start - self.step, -self.step) \ No newline at end of file