Minor fixes and changes, renamed nodump option to noDump, added missing support for mode flag. Minor additions and style fixes to parser and compiler
This commit is contained in:
parent
8b0d6b7ebe
commit
2187aa19d8
|
@ -56,7 +56,7 @@ Options
|
||||||
-h, --help Show this help text and exits
|
-h, --help Show this help text and exits
|
||||||
-v, --version Print the current peon version and exits
|
-v, --version Print the current peon version and exits
|
||||||
-s, --string Execute the passed string as if it was a file
|
-s, --string Execute the passed string as if it was a file
|
||||||
-n, --nodump Don't dump the result of compilation to a *.pbc file
|
-n, --noDump Don't dump the result of compilation to a *.pbc file
|
||||||
-b, --breakpoints Run the debugger at specific bytecode offsets (comma-separated).
|
-b, --breakpoints Run the debugger at specific bytecode offsets (comma-separated).
|
||||||
Only available when compiled with VM debugging on
|
Only available when compiled with VM debugging on
|
||||||
-d, --disassemble Disassemble the given bytecode file instead of executing it
|
-d, --disassemble Disassemble the given bytecode file instead of executing it
|
||||||
|
@ -65,5 +65,5 @@ Options
|
||||||
--warnings Turn warnings on/off (default: on). Acceptable values are
|
--warnings Turn warnings on/off (default: on). Acceptable values are
|
||||||
yes/on and no/off
|
yes/on and no/off
|
||||||
--noWarn Disable a specific warning (for example, --noWarn unusedVariable)
|
--noWarn Disable a specific warning (for example, --noWarn unusedVariable)
|
||||||
--showMismatches Show all mismatches when dispatching function calls (quite verbose!)
|
--showMismatches Show all mismatches when dispatching function calls fails (quite verbose!)
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -277,7 +277,6 @@ proc handleErrorPragma(self: Compiler, pragma: Pragma, name: Name)
|
||||||
proc dispatchPragmas(self: Compiler, name: Name)
|
proc dispatchPragmas(self: Compiler, name: Name)
|
||||||
proc dispatchDelayedPragmas(self: Compiler, name: Name)
|
proc dispatchDelayedPragmas(self: Compiler, name: Name)
|
||||||
proc funDecl(self: Compiler, node: FunDecl, name: Name)
|
proc funDecl(self: Compiler, node: FunDecl, name: Name)
|
||||||
proc typeDecl(self: Compiler, node: TypeDecl, name: Name)
|
|
||||||
proc compileModule(self: Compiler, module: Name)
|
proc compileModule(self: Compiler, module: Name)
|
||||||
proc generateCall(self: Compiler, fn: Name, args: seq[Expression], line: int)
|
proc generateCall(self: Compiler, fn: Name, args: seq[Expression], line: int)
|
||||||
proc prepareFunction(self: Compiler, fn: Name)
|
proc prepareFunction(self: Compiler, fn: Name)
|
||||||
|
@ -351,7 +350,9 @@ proc error(self: Compiler, message: string, node: ASTNode = nil) {.raises: [Comp
|
||||||
|
|
||||||
|
|
||||||
proc warning(self: Compiler, kind: WarningKind, message: string, name: Name = nil, node: ASTNode = nil) =
|
proc warning(self: Compiler, kind: WarningKind, message: string, name: Name = nil, node: ASTNode = nil) =
|
||||||
## Raises a warning
|
## Raises a warning. Note that warnings are always disabled in REPL mode
|
||||||
|
if self.replMode or kind in self.disabledWarnings:
|
||||||
|
return
|
||||||
var node: ASTNode = node
|
var node: ASTNode = node
|
||||||
var fn: Declaration
|
var fn: Declaration
|
||||||
if name.isNil():
|
if name.isNil():
|
||||||
|
@ -370,19 +371,28 @@ proc warning(self: Compiler, kind: WarningKind, message: string, name: Name = ni
|
||||||
if not name.isNil():
|
if not name.isNil():
|
||||||
file = name.owner.file
|
file = name.owner.file
|
||||||
var pos = node.getRelativeBoundaries()
|
var pos = node.getRelativeBoundaries()
|
||||||
#let line = self.source.splitLines()[node.token.line - 1].strip(chars={'\n'})
|
|
||||||
if file notin ["<string>", ""]:
|
if file notin ["<string>", ""]:
|
||||||
file = relativePath(file, getCurrentDir())
|
file = relativePath(file, getCurrentDir())
|
||||||
if kind notin self.disabledWarnings:
|
|
||||||
stderr.styledWrite(fgYellow, styleBright, "Warning in ", fgRed, &"{file}:{node.token.line}:{pos.start}")
|
stderr.styledWrite(fgYellow, styleBright, "Warning in ", fgRed, &"{file}:{node.token.line}:{pos.start}")
|
||||||
if not fn.isNil() and fn.kind == funDecl:
|
if not fn.isNil() and fn.kind == funDecl:
|
||||||
stderr.styledWrite(fgYellow, styleBright, " in function ", fgRed, FunDecl(fn).name.token.lexeme)
|
stderr.styledWrite(fgYellow, styleBright, " in function ", fgRed, FunDecl(fn).name.token.lexeme)
|
||||||
stderr.styledWriteLine(styleBright, fgDefault, ": ", message)
|
stderr.styledWriteLine(styleBright, fgDefault, ": ", message)
|
||||||
#[
|
try:
|
||||||
|
# We try to be as specific as possible with the warning message, pointing to the
|
||||||
|
# line it belongs to, but since warnings are almost never raised from the source
|
||||||
|
# file they're generated in, we take into account the fact that retrieving the
|
||||||
|
# exact warning location may fail and bail out silently if it does
|
||||||
|
let line = readFile(file).splitLines()[node.token.line - 1].strip(chars={'\n'})
|
||||||
stderr.styledWrite(fgYellow, styleBright, "Source line: ", resetStyle, fgDefault, line[0..<pos.start])
|
stderr.styledWrite(fgYellow, styleBright, "Source line: ", resetStyle, fgDefault, line[0..<pos.start])
|
||||||
stderr.styledWrite(fgYellow, styleUnderscore, line[pos.start..pos.stop])
|
stderr.styledWrite(fgYellow, styleUnderscore, line[pos.start..pos.stop])
|
||||||
stderr.styledWriteLine(fgDefault, line[pos.stop + 1..^1])
|
stderr.styledWriteLine(fgDefault, line[pos.stop + 1..^1])
|
||||||
]#
|
except IOError:
|
||||||
|
discard
|
||||||
|
except OSError:
|
||||||
|
discard
|
||||||
|
except IndexDefect:
|
||||||
|
# Something probably went wrong (wrong line metadata): bad idea to crash!
|
||||||
|
discard
|
||||||
|
|
||||||
|
|
||||||
proc step(self: Compiler): ASTNode {.inline.} =
|
proc step(self: Compiler): ASTNode {.inline.} =
|
||||||
|
@ -629,8 +639,6 @@ proc compileDecl(self: Compiler, name: Name) =
|
||||||
# Now we just dispatch to one of our functions to
|
# Now we just dispatch to one of our functions to
|
||||||
# compile the declaration
|
# compile the declaration
|
||||||
case name.kind:
|
case name.kind:
|
||||||
of NameKind.CustomType:
|
|
||||||
self.typeDecl(TypeDecl(name.node), name)
|
|
||||||
of NameKind.Function:
|
of NameKind.Function:
|
||||||
# Generic functions need to be compiled at
|
# Generic functions need to be compiled at
|
||||||
# the call site because we need to know the
|
# the call site because we need to know the
|
||||||
|
@ -1175,14 +1183,14 @@ proc matchImpl(self: Compiler, name: string, kind: Type, node: ASTNode = nil, al
|
||||||
if name.valueType.kind != Function:
|
if name.valueType.kind != Function:
|
||||||
msg &= ": not a callable"
|
msg &= ": not a callable"
|
||||||
elif kind.args.len() != name.valueType.args.len():
|
elif kind.args.len() != name.valueType.args.len():
|
||||||
msg &= &": wrong number of arguments ({name.valueType.args.len()} expected, got {kind.args.len()})"
|
msg &= &": wrong number of arguments (expected {name.valueType.args.len()}, got {kind.args.len()})"
|
||||||
else:
|
else:
|
||||||
for i, arg in kind.args:
|
for i, arg in kind.args:
|
||||||
if name.valueType.args[i].kind.mutable and not arg.kind.mutable:
|
if name.valueType.args[i].kind.mutable and not arg.kind.mutable:
|
||||||
msg &= &": first mismatch at position {i + 1}: {name.valueType.args[i].name} is immutable, not 'var'"
|
msg &= &": first mismatch at position {i + 1}: {name.valueType.args[i].name} is immutable, not 'var'"
|
||||||
break
|
break
|
||||||
elif not self.compare(arg.kind, name.valueType.args[i].kind):
|
elif not self.compare(arg.kind, name.valueType.args[i].kind):
|
||||||
msg &= &": first mismatch at position {i + 1}: ({self.typeToStr(name.valueType.args[i].kind)} expected, got {self.typeToStr(arg.kind)})"
|
msg &= &": first mismatch at position {i + 1}: (expected {self.typeToStr(name.valueType.args[i].kind)}, got {self.typeToStr(arg.kind)})"
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
msg &= " (compile with --showMismatches for more details)"
|
msg &= " (compile with --showMismatches for more details)"
|
||||||
|
@ -1380,10 +1388,7 @@ proc endScope(self: Compiler) =
|
||||||
# (it may need them later)
|
# (it may need them later)
|
||||||
names.delete(names.high())
|
names.delete(names.high())
|
||||||
continue
|
continue
|
||||||
if not name.resolved and not self.replMode:
|
if not name.resolved:
|
||||||
# We don't emit this warning in replMode because
|
|
||||||
# a variable might be declared on one line and then
|
|
||||||
# used on the next
|
|
||||||
case name.kind:
|
case name.kind:
|
||||||
of NameKind.Var:
|
of NameKind.Var:
|
||||||
if not name.ident.token.lexeme.startsWith("_") and name.isPrivate:
|
if not name.ident.token.lexeme.startsWith("_") and name.isPrivate:
|
||||||
|
@ -1452,13 +1457,13 @@ proc declareName(self: Compiler, node: ASTNode, mutable: bool = false) =
|
||||||
## on the stack
|
## on the stack
|
||||||
var declaredName: string = ""
|
var declaredName: string = ""
|
||||||
var n: Name
|
var n: Name
|
||||||
case node.kind:
|
|
||||||
of NodeKind.varDecl:
|
|
||||||
var node = VarDecl(node)
|
|
||||||
if self.names.high() > 16777215:
|
if self.names.high() > 16777215:
|
||||||
# If someone ever hits this limit in real-world scenarios, I swear I'll
|
# If someone ever hits this limit in real-world scenarios, I swear I'll
|
||||||
# slap myself 100 times with a sign saying "I'm dumb". Mark my words
|
# slap myself 100 times with a sign saying "I'm dumb". Mark my words
|
||||||
self.error("cannot declare more than 16777215 variables at a time")
|
self.error("cannot declare more than 16777215 names at a time")
|
||||||
|
case node.kind:
|
||||||
|
of NodeKind.varDecl:
|
||||||
|
var node = VarDecl(node)
|
||||||
declaredName = node.name.token.lexeme
|
declaredName = node.name.token.lexeme
|
||||||
# Creates a new Name entry so that self.identifier emits the proper stack offset
|
# Creates a new Name entry so that self.identifier emits the proper stack offset
|
||||||
self.names.add(Name(depth: self.depth,
|
self.names.add(Name(depth: self.depth,
|
||||||
|
@ -2502,10 +2507,6 @@ proc varDecl(self: Compiler, node: VarDecl) =
|
||||||
name.valueType = typ
|
name.valueType = typ
|
||||||
|
|
||||||
|
|
||||||
proc typeDecl(self: Compiler, node: TypeDecl, name: Name) =
|
|
||||||
## Compiles type declarations
|
|
||||||
# TODO
|
|
||||||
|
|
||||||
|
|
||||||
proc funDecl(self: Compiler, node: FunDecl, name: Name) =
|
proc funDecl(self: Compiler, node: FunDecl, name: Name) =
|
||||||
## Compiles function declarations
|
## Compiles function declarations
|
||||||
|
|
|
@ -139,7 +139,11 @@ proc newOperatorTable: OperatorTable =
|
||||||
result.tokens = @[]
|
result.tokens = @[]
|
||||||
for prec in Precedence:
|
for prec in Precedence:
|
||||||
result.precedence[prec] = @[]
|
result.precedence[prec] = @[]
|
||||||
result.addOperator("=") # Assignment is the only builtin
|
# Assignment and attribute accessing are (currently)
|
||||||
|
# the only builtins that cannot be easily implemented
|
||||||
|
# from within peon itself
|
||||||
|
result.addOperator("=")
|
||||||
|
result.addOperator(".")
|
||||||
|
|
||||||
|
|
||||||
proc getPrecedence(self: OperatorTable, lexeme: string): Precedence =
|
proc getPrecedence(self: OperatorTable, lexeme: string): Precedence =
|
||||||
|
@ -1293,7 +1297,6 @@ proc parse*(self: Parser, tokens: seq[Token], file: string, lines: seq[tuple[sta
|
||||||
self.tree = @[]
|
self.tree = @[]
|
||||||
if not persist:
|
if not persist:
|
||||||
self.operators = newOperatorTable()
|
self.operators = newOperatorTable()
|
||||||
self.operators.addOperator("=")
|
|
||||||
self.findOperators(tokens)
|
self.findOperators(tokens)
|
||||||
while not self.done():
|
while not self.done():
|
||||||
self.tree.add(self.declaration())
|
self.tree.add(self.declaration())
|
||||||
|
|
13
src/main.nim
13
src/main.nim
|
@ -261,12 +261,21 @@ when isMainModule:
|
||||||
var breaks: seq[uint64] = @[]
|
var breaks: seq[uint64] = @[]
|
||||||
var dis: bool = false
|
var dis: bool = false
|
||||||
var mismatches: bool = false
|
var mismatches: bool = false
|
||||||
|
var mode: CompileMode = CompileMode.Debug
|
||||||
for kind, key, value in optParser.getopt():
|
for kind, key, value in optParser.getopt():
|
||||||
case kind:
|
case kind:
|
||||||
of cmdArgument:
|
of cmdArgument:
|
||||||
file = key
|
file = key
|
||||||
of cmdLongOption:
|
of cmdLongOption:
|
||||||
case key:
|
case key:
|
||||||
|
of "mode":
|
||||||
|
if value.toLowerAscii() == "release":
|
||||||
|
mode = CompileMode.Release
|
||||||
|
elif value.toLowerAscii() == "debug":
|
||||||
|
discard
|
||||||
|
else:
|
||||||
|
stderr.styledWriteLine(fgRed, styleBright, "Error: ", fgDefault, "invalid value for option 'mode' (valid options are: debug, release)")
|
||||||
|
quit()
|
||||||
of "help":
|
of "help":
|
||||||
echo HELP_MESSAGE
|
echo HELP_MESSAGE
|
||||||
quit()
|
quit()
|
||||||
|
@ -276,7 +285,7 @@ when isMainModule:
|
||||||
of "string":
|
of "string":
|
||||||
file = key
|
file = key
|
||||||
fromString = true
|
fromString = true
|
||||||
of "no-dump":
|
of "noDump":
|
||||||
dump = false
|
dump = false
|
||||||
of "warnings":
|
of "warnings":
|
||||||
if value.toLowerAscii() in ["yes", "on"]:
|
if value.toLowerAscii() in ["yes", "on"]:
|
||||||
|
@ -349,7 +358,7 @@ when isMainModule:
|
||||||
if file == "":
|
if file == "":
|
||||||
repl()
|
repl()
|
||||||
else:
|
else:
|
||||||
runFile(file, fromString, dump, breaks, dis, warnings, mismatches)
|
runFile(file, fromString, dump, breaks, dis, warnings, mismatches, mode)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue