Minor refactoring to value representation, needs a fix to the function pointers

This commit is contained in:
nocturn9x 2020-08-09 21:45:50 +02:00
parent 382e92f900
commit fe07ed4f49
6 changed files with 70 additions and 25 deletions

View File

@ -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 =

View File

@ -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

BIN
nim/main Executable file

Binary file not shown.

View File

@ -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}"

View File

@ -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)

1
nim/stuff.jpl Normal file
View File

@ -0,0 +1 @@
1 + 2 * 3