Many fixes to generics

This commit is contained in:
Mattia Giambirtone 2022-12-01 22:04:10 +01:00
parent 63cdda42ce
commit 8fb90bb0ef
12 changed files with 356 additions and 419 deletions

File diff suppressed because it is too large Load Diff

View File

@ -668,6 +668,7 @@ proc lex*(self: Lexer, source, file: string): seq[Token] =
self.start = self.current
self.lineCurrent = self.linePos
self.tokens.add(Token(kind: EndOfFile, lexeme: "",
line: self.line, pos: (self.current, self.current)))
line: self.line, pos: (self.current, self.current),
relPos: (start: 0, stop: self.linePos - 1)))
self.incLine()
return self.tokens

View File

@ -73,12 +73,8 @@ type
hexExpr,
octExpr,
binExpr,
nilExpr,
nanExpr,
infExpr,
identExpr, # Identifier
pragmaExpr,
varExpr,
refExpr,
ptrExpr
@ -131,9 +127,6 @@ type
TrueExpr* = ref object of LiteralExpr
FalseExpr* = ref object of LiteralExpr
NilExpr* = ref object of LiteralExpr
NanExpr* = ref object of LiteralExpr
InfExpr* = ref object of LiteralExpr
IdentExpr* = ref object of Expression
name*: Token
@ -300,19 +293,12 @@ proc isConst*(self: ASTNode): bool =
## constants
case self.kind:
of intExpr, hexExpr, binExpr, octExpr, strExpr, falseExpr, trueExpr,
infExpr, nanExpr, floatExpr, nilExpr:
floatExpr:
return true
else:
return false
proc isLiteral*(self: ASTNode): bool {.inline.} =
## Returns if the AST node represents a literal
self.kind in {intExpr, hexExpr, binExpr, octExpr,
strExpr, falseExpr, trueExpr, infExpr,
nanExpr, floatExpr, nilExpr
}
## AST node constructors
proc newASTNode*(kind: NodeKind, token: Token): ASTNode =
## Initializes a new generic ASTNode object
@ -329,13 +315,6 @@ proc newPragma*(name: IdentExpr, args: seq[LiteralExpr]): Pragma =
result.token = name.token
proc newVarExpr*(expression: Expression, token: Token): Var =
new(result)
result.kind = varExpr
result.value = expression
result.token = token
proc newRefExpr*(expression: Expression, token: Token): Ref =
new(result)
result.kind = refExpr
@ -384,12 +363,6 @@ proc newTrueExpr*(token: Token): LiteralExpr = LiteralExpr(kind: trueExpr,
token: token, literal: token)
proc newFalseExpr*(token: Token): LiteralExpr = LiteralExpr(kind: falseExpr,
token: token, literal: token)
proc newNaNExpr*(token: Token): LiteralExpr = LiteralExpr(kind: nanExpr,
token: token, literal: token)
proc newNilExpr*(token: Token): LiteralExpr = LiteralExpr(kind: nilExpr,
token: token, literal: token)
proc newInfExpr*(token: Token): LiteralExpr = LiteralExpr(kind: infExpr,
token: token, literal: token)
proc newStrExpr*(literal: Token): StrExpr =
@ -667,8 +640,8 @@ proc `$`*(self: ASTNode): string =
return "nil"
case self.kind:
of intExpr, floatExpr, hexExpr, binExpr, octExpr, strExpr, trueExpr,
falseExpr, nanExpr, nilExpr, infExpr:
if self.kind in {trueExpr, falseExpr, nanExpr, nilExpr, infExpr}:
falseExpr:
if self.kind in {trueExpr, falseExpr}:
result &= &"Literal({($self.kind)[0..^5]})"
elif self.kind == strExpr:
result &= &"Literal({LiteralExpr(self).literal.lexeme[1..^2].escape()})"
@ -773,10 +746,8 @@ proc `$`*(self: ASTNode): string =
of pragmaExpr:
var self = Pragma(self)
result &= &"Pragma(name={self.name}, args={self.args})"
of varExpr:
result &= &"Var({Var(self).value})"
of refExpr:
result &= &"Ptr({Ref(self).value})"
result &= &"Ref({Ref(self).value})"
of ptrExpr:
result &= &"Ptr({Ptr(self).value})"
else:

View File

@ -271,7 +271,7 @@ const argumentDoubleInstructions* = {PopN, }
# Jump instructions jump at relative or absolute bytecode offsets
const jumpInstructions* = {Jump, JumpIfFalse, JumpIfFalsePop,
JumpForwards, JumpBackwards,
JumpIfTrue}
JumpIfTrue, JumpIfFalseOrPop}
proc newChunk*: Chunk =

View File

@ -24,9 +24,6 @@ type
# Booleans
True, False,
# Other singleton types
Infinity, NotANumber, Nil
# Control flow statements
If, Else,

View File

@ -317,10 +317,6 @@ proc primary(self: Parser): Expression =
result = newTrueExpr(self.step())
of False:
result = newFalseExpr(self.step())
of TokenType.NotANumber:
result = newNanExpr(self.step())
of Nil:
result = newNilExpr(self.step())
of Float:
result = newFloatExpr(self.step())
of Integer:
@ -343,7 +339,7 @@ proc primary(self: Parser): Expression =
result = newYieldExpr(self.expression(), tok)
else:
# Empty yield
result = newYieldExpr(newNilExpr(Token()), tok)
result = newYieldExpr(nil, tok)
of Await:
let tok = self.step()
if self.currentFunction.isNil():
@ -364,8 +360,6 @@ proc primary(self: Parser): Expression =
result = newBinExpr(self.step())
of String:
result = newStrExpr(self.step())
of Infinity:
result = newInfExpr(self.step())
of Function:
discard self.step()
result = Expression(self.funDecl(isLambda=true))
@ -375,9 +369,6 @@ proc primary(self: Parser): Expression =
of Generator:
discard self.step()
result = Expression(self.funDecl(isGenerator=true, isLambda=true))
of TokenType.Var:
discard self.step()
result = newVarExpr(self.expression(), self.peek(-1))
of TokenType.Ref:
discard self.step()
result = newRefExpr(self.expression(), self.peek(-1))
@ -654,7 +645,7 @@ proc yieldStmt(self: Parser): Statement =
if not self.check(Semicolon):
result = newYieldStmt(self.expression(), tok)
else:
result = newYieldStmt(newNilExpr(Token(lexeme: "nil")), tok)
result = newYieldStmt(nil, tok)
endOfLine("missing semicolon after 'yield'")
@ -857,7 +848,8 @@ proc parsePragmas(self: Parser): seq[Pragma] =
elif self.match("("):
while not self.match(")") and not self.done():
exp = self.primary()
if not exp.isLiteral():
if exp.kind notin {strExpr, intExpr, octExpr, binExpr, hexExpr, floatExpr,
trueExpr, falseExpr}:
self.error("pragma arguments can only be literals", exp.token)
args.add(LiteralExpr(exp))
if not self.match(","):
@ -865,7 +857,8 @@ proc parsePragmas(self: Parser): seq[Pragma] =
self.expect(LeftParen, "unterminated parenthesis in pragma arguments")
else:
exp = self.primary()
if not exp.isLiteral():
if exp.kind notin {strExpr, intExpr, octExpr, binExpr, hexExpr, floatExpr,
trueExpr, falseExpr}:
self.error("pragma arguments can only be literals", exp.token)
args.add(LiteralExpr(exp))
result.add(newPragma(name, args))

View File

@ -9,30 +9,6 @@ fn clock*: float {
}
fn print*(x: int) {
#pragma[magic: "PrintInt64"]
fn print*[T: Number | string | bool | nan | inf](x: T) {
#pragma[magic: "print"]
}
fn print*(x: int32) {
#pragma[magic: "PrintInt32"]
}
fn print*(x: uint64) {
#pragma[magic: "PrintUInt64"]
}
fn print*(x: float) {
#pragma[magic: "PrintFloat64"]
}
fn print*(x: string) {
#pragma[magic: "PrintString"]
}
fn print*(x: bool) {
#pragma[magic: "PrintBool"]
}

View File

@ -1,23 +1,73 @@
# Stub type declarations for peon's intrinsic types
type int64* = object {#pragma[magic: "int64"]}
type int32* = object {#pragma[magic: "int32"]}
type int16* = object {#pragma[magic: "int16"]}
type int8* = object {#pragma[magic: "int8"]}
type uint64* = object {#pragma[magic: "uint64"]}
type uint32* = object {#pragma[magic: "uint32"]}
type uint16* = object {#pragma[magic: "uint16"]}
type uint8* = object {#pragma[magic: "uint8"]}
type float64* = object {#pragma[magic: "float64"]}
type float32* = object {#pragma[magic: "float32"]}
type bool* = object {#pragma[magic: "bool"]}
type string* = object {#pragma[magic: "string"]}
type any* = object {#pragma[magic: "any"]}
type int64* = object {
#pragma[magic: "int64"]
}
type int32* = object {
#pragma[magic: "int32"]
}
type int16* = object {
#pragma[magic: "int16"]
}
type int8* = object {
#pragma[magic: "int8"]
}
type uint64* = object {
#pragma[magic: "uint64"]
}
type uint32* = object {
#pragma[magic: "uint32"]
}
type uint16* = object {
#pragma[magic: "uint16"]
}
type uint8* = object {
#pragma[magic: "uint8"]
}
type float64* = object {
#pragma[magic: "float64"]
}
type float32* = object {
#pragma[magic: "float32"]
}
type bool* = object {
#pragma[magic: "bool"]
}
type string* = object {
#pragma[magic: "string"]
}
type any* = object {
#pragma[magic: "any"]
}
type inf* = object {
#pragma[magic: "inf"]
}
type nil* = object {
#pragma[magic: "nil"]
}
type nan* = object {
#pragma[magic: "nan"]
}
# Some convenience aliases
type int* = int64;
type float* = float64;
type int* = int64;
type float* = float64;
type SignedInteger* = int64 | int32 | int16 | int8;
type UnsignedInteger* = uint64 | uint32 | uint16 | uint8;
type Integer* = SignedInteger | UnsignedInteger;

View File

@ -51,9 +51,6 @@ proc fillSymbolTable*(tokenizer: Lexer) =
# but we don't need to care about that until
# we're in the parsing/compilation steps so
# it's fine
tokenizer.symbols.addKeyword("nan", NotANumber)
tokenizer.symbols.addKeyword("inf", Infinity)
tokenizer.symbols.addKeyword("nil", TokenType.Nil)
tokenizer.symbols.addKeyword("true", True)
tokenizer.symbols.addKeyword("false", False)
tokenizer.symbols.addKeyword("ref", TokenType.Ref)

View File

@ -19,4 +19,4 @@ fn fooBar(a, b: int): int {
noReturn(1);
print(fooBar(1, 3) == 1); # true
print(fooBar(1, 3) == 1); # true

View File

@ -1,4 +1,4 @@
# Another test for generic functions
# A test for generic functions
import std;
@ -9,4 +9,4 @@ fn sum[T: int | int32](a, b: T): T {
print(sum(1, 2)); # Prints 3
print(sum(1'i32, 2'i32)); # Also prints 3!
#print(sum(1.0, 2.0)); # Will fail to compile
#print(sum(1.0, 2.0)); # Will fail to compile

View File

@ -1,4 +1,6 @@
# Tests more stuff about generics. This test should fail to compile
import std;
fn identity(x: int32): int32 {
return x;