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:
Mattia Giambirtone 2022-11-28 14:04:12 +01:00
parent 8b0d6b7ebe
commit 2187aa19d8
4 changed files with 49 additions and 36 deletions

View File

@ -56,7 +56,7 @@ Options
-h, --help Show this help text and exits
-v, --version Print the current peon version and exits
-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).
Only available when compiled with VM debugging on
-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
yes/on and no/off
--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!)
"""

View File

@ -277,7 +277,6 @@ proc handleErrorPragma(self: Compiler, pragma: Pragma, name: Name)
proc dispatchPragmas(self: Compiler, name: Name)
proc dispatchDelayedPragmas(self: Compiler, 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 generateCall(self: Compiler, fn: Name, args: seq[Expression], line: int)
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) =
## 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 fn: Declaration
if name.isNil():
@ -370,19 +371,28 @@ proc warning(self: Compiler, kind: WarningKind, message: string, name: Name = ni
if not name.isNil():
file = name.owner.file
var pos = node.getRelativeBoundaries()
#let line = self.source.splitLines()[node.token.line - 1].strip(chars={'\n'})
if file notin ["<string>", ""]:
file = relativePath(file, getCurrentDir())
if kind notin self.disabledWarnings:
stderr.styledWrite(fgYellow, styleBright, "Warning in ", fgRed, &"{file}:{node.token.line}:{pos.start}")
if not fn.isNil() and fn.kind == funDecl:
stderr.styledWrite(fgYellow, styleBright, " in function ", fgRed, FunDecl(fn).name.token.lexeme)
stderr.styledWriteLine(styleBright, fgDefault, ": ", message)
#[
stderr.styledWrite(fgYellow, styleBright, "Source line: ", resetStyle, fgDefault, line[0..<pos.start])
stderr.styledWrite(fgYellow, styleUnderscore, line[pos.start..pos.stop])
stderr.styledWriteLine(fgDefault, line[pos.stop + 1..^1])
]#
stderr.styledWrite(fgYellow, styleBright, "Warning in ", fgRed, &"{file}:{node.token.line}:{pos.start}")
if not fn.isNil() and fn.kind == funDecl:
stderr.styledWrite(fgYellow, styleBright, " in function ", fgRed, FunDecl(fn).name.token.lexeme)
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, styleUnderscore, line[pos.start..pos.stop])
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.} =
@ -629,8 +639,6 @@ proc compileDecl(self: Compiler, name: Name) =
# Now we just dispatch to one of our functions to
# compile the declaration
case name.kind:
of NameKind.CustomType:
self.typeDecl(TypeDecl(name.node), name)
of NameKind.Function:
# Generic functions need to be compiled at
# 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:
msg &= ": not a callable"
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:
for i, arg in kind.args:
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'"
break
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
else:
msg &= " (compile with --showMismatches for more details)"
@ -1380,10 +1388,7 @@ proc endScope(self: Compiler) =
# (it may need them later)
names.delete(names.high())
continue
if not name.resolved and not self.replMode:
# We don't emit this warning in replMode because
# a variable might be declared on one line and then
# used on the next
if not name.resolved:
case name.kind:
of NameKind.Var:
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
var declaredName: string = ""
var n: Name
if self.names.high() > 16777215:
# 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
self.error("cannot declare more than 16777215 names at a time")
case node.kind:
of NodeKind.varDecl:
var node = VarDecl(node)
if self.names.high() > 16777215:
# 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
self.error("cannot declare more than 16777215 variables at a time")
declaredName = node.name.token.lexeme
# Creates a new Name entry so that self.identifier emits the proper stack offset
self.names.add(Name(depth: self.depth,
@ -2500,11 +2505,7 @@ proc varDecl(self: Compiler, node: VarDecl) =
self.declareName(node)
var name = self.names[^1]
name.valueType = typ
proc typeDecl(self: Compiler, node: TypeDecl, name: Name) =
## Compiles type declarations
# TODO
proc funDecl(self: Compiler, node: FunDecl, name: Name) =

View File

@ -139,7 +139,11 @@ proc newOperatorTable: OperatorTable =
result.tokens = @[]
for prec in Precedence:
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 =
@ -1293,7 +1297,6 @@ proc parse*(self: Parser, tokens: seq[Token], file: string, lines: seq[tuple[sta
self.tree = @[]
if not persist:
self.operators = newOperatorTable()
self.operators.addOperator("=")
self.findOperators(tokens)
while not self.done():
self.tree.add(self.declaration())

View File

@ -261,12 +261,21 @@ when isMainModule:
var breaks: seq[uint64] = @[]
var dis: bool = false
var mismatches: bool = false
var mode: CompileMode = CompileMode.Debug
for kind, key, value in optParser.getopt():
case kind:
of cmdArgument:
file = key
of cmdLongOption:
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":
echo HELP_MESSAGE
quit()
@ -276,7 +285,7 @@ when isMainModule:
of "string":
file = key
fromString = true
of "no-dump":
of "noDump":
dump = false
of "warnings":
if value.toLowerAscii() in ["yes", "on"]:
@ -349,7 +358,7 @@ when isMainModule:
if file == "":
repl()
else:
runFile(file, fromString, dump, breaks, dis, warnings, mismatches)
runFile(file, fromString, dump, breaks, dis, warnings, mismatches, mode)