Skip to content

Commit

Permalink
Implement pow and floordiv
Browse files Browse the repository at this point in the history
  • Loading branch information
Seggan committed Dec 13, 2023
1 parent affbf2c commit fa9cda3
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 14 deletions.
5 changes: 4 additions & 1 deletion docs/index.papyri
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ fun highlight(tokens: List<Token>): 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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ enum class BinOp(internal val generateCode: InsnsBuilder.(List<FullInsn>, List<F
MINUS("__minus__"),
TIMES("__times__"),
DIV("__div__"),
FLOORDIV("__floordiv__"),
MOD("__mod__"),
POW("__pow__"),
RANGE("__range__"),
INCLUSIVE_RANGE("__inclrange__"),
INCLUSIVE_RANGE("__inclRange__"),
BAND("__band__"),
BOR("__bor__"),
BXOR("__bxor__"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ object Lexer {
text("+", Token.Type.PLUS)
text("-", Token.Type.MINUS)
text("*", Token.Type.STAR)
text("**", Token.Type.DOUBLE_STAR)
text("/", Token.Type.SLASH)
text("//", Token.Type.DOUBLE_SLASH)
text("%", Token.Type.PERCENT)
text("&", Token.Type.BAND)
text("|", Token.Type.BOR)
Expand Down Expand Up @@ -229,7 +231,9 @@ data class Token(val type: Type, val text: String, val span: Span) {
PLUS("'+'"),
MINUS("'-'"),
STAR("'*'"),
DOUBLE_STAR("'**'"),
SLASH("'/'"),
DOUBLE_SLASH("'//'"),
PERCENT("'%'"),
BAND("'&'"),
BOR("'|'"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ class Parser(tokens: List<Token>, 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,
Expand All @@ -127,8 +128,13 @@ class Parser(tokens: List<Token>, 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))
Expand All @@ -142,9 +148,23 @@ class Parser(tokens: List<Token>, 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)
Expand All @@ -159,7 +179,16 @@ class Parser(tokens: List<Token>, 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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}
Expand Down
2 changes: 1 addition & 1 deletion metis-lang/src/main/resources/core/list.metis
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion metis-lang/src/main/resources/core/range.metis
Original file line number Diff line number Diff line change
Expand Up @@ -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)

0 comments on commit fa9cda3

Please sign in to comment.