mirror of https://github.com/japl-lang/japl.git
Minor refactoring to value representation, needs a fix to the function pointers
This commit is contained in:
parent
382e92f900
commit
fe07ed4f49
|
@ -108,6 +108,7 @@ proc emitConstant(self: Compiler, value: Value) =
|
|||
else:
|
||||
self.emitBytes(OP_CONSTANT, self.makeConstant(value))
|
||||
|
||||
|
||||
proc getRule(kind: TokenType): ParseRule # Forward declaration
|
||||
|
||||
|
||||
|
@ -116,7 +117,16 @@ proc endCompiler(self: Compiler) =
|
|||
|
||||
|
||||
proc parsePrecedence(self: Compiler, precedence: Precedence) =
|
||||
return
|
||||
discard self.parser.advance()
|
||||
var prefixRule = getRule(self.parser.previous.kind).prefix
|
||||
if prefixRule == nil:
|
||||
self.parser.parseError(self.parser.peek, "Expecting expression")
|
||||
return
|
||||
self.prefixRule()
|
||||
var precedence = int precedence
|
||||
while precedence <= (int getRule(self.parser.peek.kind).precedence):
|
||||
var infixRule = getRule(self.parser.previous().kind).infix
|
||||
self.infixRule()
|
||||
|
||||
|
||||
proc expression(self: Compiler) =
|
||||
|
@ -166,7 +176,7 @@ proc grouping(self: Compiler) =
|
|||
self.parser.consume(RP, "Expecting ')' after parenthesized expression")
|
||||
|
||||
|
||||
var rules: array[39, ParseRule] = [
|
||||
var rules: array[TokenType, ParseRule] = [
|
||||
makeRule(grouping, nil, PREC_NONE), # LP
|
||||
makeRule(nil, nil, PREC_NONE), # RP
|
||||
makeRule(nil, nil, PREC_NONE), # LB
|
||||
|
@ -210,7 +220,7 @@ var rules: array[39, ParseRule] = [
|
|||
|
||||
|
||||
proc getRule(kind: TokenType): ParseRule =
|
||||
return rules[int kind]
|
||||
return rules[kind]
|
||||
|
||||
|
||||
proc compile*(self: Compiler, source: string, chunk: Chunk): bool =
|
||||
|
|
|
@ -92,7 +92,7 @@ proc parseString(self: var Lexer, delimiter: char) =
|
|||
if self.done():
|
||||
quit(&"Unterminated string literal at {self.line}")
|
||||
discard self.step()
|
||||
let value = Value(kind: ValueTypes.STRING, stringValue: self.source[self.start..<self.current - 1]) # Get the value between quotes
|
||||
let value = Value(kind: ValueTypes.OBJECT, obj: Obj(kind: ObjectTypes.STRING, str: self.source[self.start..<self.current - 1])) # Get the value between quotes
|
||||
let token = self.createToken(STR, value)
|
||||
self.tokens.add(token)
|
||||
|
||||
|
@ -117,9 +117,9 @@ proc parseIdentifier(self: var Lexer) =
|
|||
var text: string = self.source[self.start..<self.current]
|
||||
var keyword = text in RESERVED
|
||||
if keyword:
|
||||
self.tokens.add(self.createToken(RESERVED[text], Value(kind: ValueTypes.STRING, stringValue: text)))
|
||||
self.tokens.add(self.createToken(RESERVED[text], Value(kind: ValueTypes.OBJECT, obj: Obj(kind: ObjectTypes.STRING, str: text))))
|
||||
else:
|
||||
self.tokens.add(self.createToken(ID, Value(kind: ValueTypes.STRING, stringValue: text)))
|
||||
self.tokens.add(self.createToken(ID, Value(kind: ValueTypes.OBJECT, obj: Obj(kind:ObjectTypes.STRING, str: text))))
|
||||
|
||||
|
||||
proc parseComment(self: var Lexer) =
|
||||
|
@ -159,17 +159,17 @@ proc scanToken(self: var Lexer) =
|
|||
elif single == '/' and self.match('*'):
|
||||
self.parseComment()
|
||||
elif single == '=' and self.match('='):
|
||||
self.tokens.add(self.createToken(DEQ, Value(kind: ValueTypes.STRING, stringValue: "==")))
|
||||
self.tokens.add(self.createToken(DEQ, Value(kind: ValueTypes.OBJECT, obj: Obj(kind: ObjectTypes.STRING, str: "=="))))
|
||||
elif single == '>' and self.match('='):
|
||||
self.tokens.add(self.createToken(GE, Value(kind: ValueTypes.STRING, stringValue: ">=")))
|
||||
self.tokens.add(self.createToken(GE, Value(kind: ValueTypes.OBJECT, obj: Obj(kind: ObjectTypes.STRING, str: ">="))))
|
||||
elif single == '<' and self.match('='):
|
||||
self.tokens.add(self.createToken(LE, Value(kind: ValueTypes.STRING, stringValue: "<=")))
|
||||
self.tokens.add(self.createToken(LE, Value(kind: ValueTypes.OBJECT, obj: Obj(kind: ObjectTypes.STRING, str: "<="))))
|
||||
elif single == '!' and self.match('='):
|
||||
self.tokens.add(self.createToken(NE, Value(kind: ValueTypes.STRING, stringValue: "!=")))
|
||||
self.tokens.add(self.createToken(NE, Value(kind: ValueTypes.OBJECT, obj: Obj(kind: ObjectTypes.STRING, str: "!="))))
|
||||
elif single == '*' and self.match('*'):
|
||||
self.tokens.add(self.createToken(POW, Value(kind: ValueTypes.STRING, stringValue: "**")))
|
||||
self.tokens.add(self.createToken(POW, Value(kind: ValueTypes.OBJECT, obj: Obj(kind: ObjectTypes.STRING, str: "**"))))
|
||||
else:
|
||||
self.tokens.add(self.createToken(TOKENS[single], Value(kind: ValueTypes.CHAR, charValue: single)))
|
||||
self.tokens.add(self.createToken(TOKENS[single], Value(kind: ValueTypes.OBJECT, obj: Obj(kind: ObjectTypes.STRING, str: &"{single}"))))
|
||||
else:
|
||||
quit(&"Unexpected character '{single}' at {self.line}")
|
||||
|
||||
|
@ -178,6 +178,6 @@ proc lex*(self: var Lexer): seq[Token] =
|
|||
while not self.done():
|
||||
self.start = self.current
|
||||
self.scanToken()
|
||||
self.tokens.add(Token(kind: EOF, lexeme: "EOF", literal: Value(kind: CHAR, charValue: '\0'), line: self.line))
|
||||
self.tokens.add(Token(kind: EOF, lexeme: "EOF", literal: Value(kind: ValueTypes.NIL), line: self.line))
|
||||
return self.tokens
|
||||
|
||||
|
|
21
nim/main.nim
21
nim/main.nim
|
@ -5,7 +5,24 @@ import os
|
|||
|
||||
|
||||
proc repl(debug: bool = false) =
|
||||
return
|
||||
var bytecodeVM = initVM()
|
||||
echo &"[JAPL 0.2.0 - Nim {NimVersion} - {CompileDate} {CompileTime}]"
|
||||
var source: string = ""
|
||||
while true:
|
||||
try:
|
||||
stdout.write(">>> ")
|
||||
source = readLine(stdin)
|
||||
except IOError:
|
||||
break
|
||||
if source == "":
|
||||
continue
|
||||
else:
|
||||
if debug:
|
||||
echo "Debug mode is enabled, bytecode will be disassembled"
|
||||
var result = bytecodeVM.interpret(source, debug)
|
||||
if debug:
|
||||
echo &"Result: {result}"
|
||||
|
||||
|
||||
proc main(file: string = "", debug: bool = false) =
|
||||
if file == "":
|
||||
|
@ -25,7 +42,7 @@ proc main(file: string = "", debug: bool = false) =
|
|||
var bytecodeVM = initVM()
|
||||
if debug:
|
||||
echo "Debug mode is enabled, bytecode will be disassembled"
|
||||
var result = bytecodeVM.interpret(source)
|
||||
var result = bytecodeVM.interpret(source, debug)
|
||||
if debug:
|
||||
echo &"Result: {result}"
|
||||
|
||||
|
|
|
@ -3,17 +3,25 @@ import strformat
|
|||
|
||||
type
|
||||
ValueTypes* = enum
|
||||
FLOAT, INT, CHAR, STRING
|
||||
Value* = ref object of RootObj
|
||||
case kind*: ValueTypes
|
||||
of CHAR:
|
||||
charValue*: char
|
||||
FLOAT, INT, BOOL, NIL, OBJECT
|
||||
ObjectTypes* = enum
|
||||
STRING,
|
||||
Obj* = ref object
|
||||
case kind*: ObjectTypes
|
||||
of STRING:
|
||||
stringValue*: string
|
||||
str*: string
|
||||
Value* = ref object
|
||||
case kind*: ValueTypes
|
||||
of FLOAT:
|
||||
floatValue*: float
|
||||
of INT:
|
||||
intValue*: int
|
||||
of BOOL:
|
||||
boolValue*: bool
|
||||
of NIL:
|
||||
discard
|
||||
of OBJECT:
|
||||
obj*: Obj
|
||||
ValueArray* = ref object
|
||||
values*: seq[Value]
|
||||
|
||||
|
@ -26,13 +34,22 @@ proc writeValueArray*(arr: var ValueArray, value: Value) =
|
|||
arr.values.add(value)
|
||||
|
||||
|
||||
proc stringifyObject(obj: Obj): string =
|
||||
case obj.kind:
|
||||
of STRING:
|
||||
return obj.str
|
||||
|
||||
|
||||
proc stringifyValue*(value: Value): string =
|
||||
case value.kind:
|
||||
of FLOAT:
|
||||
result = $value.floatValue
|
||||
of STRING:
|
||||
result = value.stringValue
|
||||
of INT:
|
||||
result = $value.intValue
|
||||
of CHAR:
|
||||
result = &"{value.charValue}"
|
||||
of BOOL:
|
||||
result = $value.boolValue
|
||||
of NIL:
|
||||
result = "none"
|
||||
of OBJECT:
|
||||
result = stringifyObject(value.obj)
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
1 + 2 * 3
|
Loading…
Reference in New Issue