Many fixes to generics
This commit is contained in:
parent
63cdda42ce
commit
8fb90bb0ef
File diff suppressed because it is too large
Load Diff
|
@ -668,6 +668,7 @@ proc lex*(self: Lexer, source, file: string): seq[Token] =
|
||||||
self.start = self.current
|
self.start = self.current
|
||||||
self.lineCurrent = self.linePos
|
self.lineCurrent = self.linePos
|
||||||
self.tokens.add(Token(kind: EndOfFile, lexeme: "",
|
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()
|
self.incLine()
|
||||||
return self.tokens
|
return self.tokens
|
||||||
|
|
|
@ -73,12 +73,8 @@ type
|
||||||
hexExpr,
|
hexExpr,
|
||||||
octExpr,
|
octExpr,
|
||||||
binExpr,
|
binExpr,
|
||||||
nilExpr,
|
|
||||||
nanExpr,
|
|
||||||
infExpr,
|
|
||||||
identExpr, # Identifier
|
identExpr, # Identifier
|
||||||
pragmaExpr,
|
pragmaExpr,
|
||||||
varExpr,
|
|
||||||
refExpr,
|
refExpr,
|
||||||
ptrExpr
|
ptrExpr
|
||||||
|
|
||||||
|
@ -131,9 +127,6 @@ type
|
||||||
|
|
||||||
TrueExpr* = ref object of LiteralExpr
|
TrueExpr* = ref object of LiteralExpr
|
||||||
FalseExpr* = 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
|
IdentExpr* = ref object of Expression
|
||||||
name*: Token
|
name*: Token
|
||||||
|
@ -300,19 +293,12 @@ proc isConst*(self: ASTNode): bool =
|
||||||
## constants
|
## constants
|
||||||
case self.kind:
|
case self.kind:
|
||||||
of intExpr, hexExpr, binExpr, octExpr, strExpr, falseExpr, trueExpr,
|
of intExpr, hexExpr, binExpr, octExpr, strExpr, falseExpr, trueExpr,
|
||||||
infExpr, nanExpr, floatExpr, nilExpr:
|
floatExpr:
|
||||||
return true
|
return true
|
||||||
else:
|
else:
|
||||||
return false
|
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
|
## AST node constructors
|
||||||
proc newASTNode*(kind: NodeKind, token: Token): ASTNode =
|
proc newASTNode*(kind: NodeKind, token: Token): ASTNode =
|
||||||
## Initializes a new generic ASTNode object
|
## Initializes a new generic ASTNode object
|
||||||
|
@ -329,13 +315,6 @@ proc newPragma*(name: IdentExpr, args: seq[LiteralExpr]): Pragma =
|
||||||
result.token = name.token
|
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 =
|
proc newRefExpr*(expression: Expression, token: Token): Ref =
|
||||||
new(result)
|
new(result)
|
||||||
result.kind = refExpr
|
result.kind = refExpr
|
||||||
|
@ -384,12 +363,6 @@ proc newTrueExpr*(token: Token): LiteralExpr = LiteralExpr(kind: trueExpr,
|
||||||
token: token, literal: token)
|
token: token, literal: token)
|
||||||
proc newFalseExpr*(token: Token): LiteralExpr = LiteralExpr(kind: falseExpr,
|
proc newFalseExpr*(token: Token): LiteralExpr = LiteralExpr(kind: falseExpr,
|
||||||
token: token, literal: token)
|
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 =
|
proc newStrExpr*(literal: Token): StrExpr =
|
||||||
|
@ -667,8 +640,8 @@ proc `$`*(self: ASTNode): string =
|
||||||
return "nil"
|
return "nil"
|
||||||
case self.kind:
|
case self.kind:
|
||||||
of intExpr, floatExpr, hexExpr, binExpr, octExpr, strExpr, trueExpr,
|
of intExpr, floatExpr, hexExpr, binExpr, octExpr, strExpr, trueExpr,
|
||||||
falseExpr, nanExpr, nilExpr, infExpr:
|
falseExpr:
|
||||||
if self.kind in {trueExpr, falseExpr, nanExpr, nilExpr, infExpr}:
|
if self.kind in {trueExpr, falseExpr}:
|
||||||
result &= &"Literal({($self.kind)[0..^5]})"
|
result &= &"Literal({($self.kind)[0..^5]})"
|
||||||
elif self.kind == strExpr:
|
elif self.kind == strExpr:
|
||||||
result &= &"Literal({LiteralExpr(self).literal.lexeme[1..^2].escape()})"
|
result &= &"Literal({LiteralExpr(self).literal.lexeme[1..^2].escape()})"
|
||||||
|
@ -773,10 +746,8 @@ proc `$`*(self: ASTNode): string =
|
||||||
of pragmaExpr:
|
of pragmaExpr:
|
||||||
var self = Pragma(self)
|
var self = Pragma(self)
|
||||||
result &= &"Pragma(name={self.name}, args={self.args})"
|
result &= &"Pragma(name={self.name}, args={self.args})"
|
||||||
of varExpr:
|
|
||||||
result &= &"Var({Var(self).value})"
|
|
||||||
of refExpr:
|
of refExpr:
|
||||||
result &= &"Ptr({Ref(self).value})"
|
result &= &"Ref({Ref(self).value})"
|
||||||
of ptrExpr:
|
of ptrExpr:
|
||||||
result &= &"Ptr({Ptr(self).value})"
|
result &= &"Ptr({Ptr(self).value})"
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -271,7 +271,7 @@ const argumentDoubleInstructions* = {PopN, }
|
||||||
# Jump instructions jump at relative or absolute bytecode offsets
|
# Jump instructions jump at relative or absolute bytecode offsets
|
||||||
const jumpInstructions* = {Jump, JumpIfFalse, JumpIfFalsePop,
|
const jumpInstructions* = {Jump, JumpIfFalse, JumpIfFalsePop,
|
||||||
JumpForwards, JumpBackwards,
|
JumpForwards, JumpBackwards,
|
||||||
JumpIfTrue}
|
JumpIfTrue, JumpIfFalseOrPop}
|
||||||
|
|
||||||
|
|
||||||
proc newChunk*: Chunk =
|
proc newChunk*: Chunk =
|
||||||
|
|
|
@ -24,9 +24,6 @@ type
|
||||||
# Booleans
|
# Booleans
|
||||||
True, False,
|
True, False,
|
||||||
|
|
||||||
# Other singleton types
|
|
||||||
Infinity, NotANumber, Nil
|
|
||||||
|
|
||||||
# Control flow statements
|
# Control flow statements
|
||||||
If, Else,
|
If, Else,
|
||||||
|
|
||||||
|
|
|
@ -317,10 +317,6 @@ proc primary(self: Parser): Expression =
|
||||||
result = newTrueExpr(self.step())
|
result = newTrueExpr(self.step())
|
||||||
of False:
|
of False:
|
||||||
result = newFalseExpr(self.step())
|
result = newFalseExpr(self.step())
|
||||||
of TokenType.NotANumber:
|
|
||||||
result = newNanExpr(self.step())
|
|
||||||
of Nil:
|
|
||||||
result = newNilExpr(self.step())
|
|
||||||
of Float:
|
of Float:
|
||||||
result = newFloatExpr(self.step())
|
result = newFloatExpr(self.step())
|
||||||
of Integer:
|
of Integer:
|
||||||
|
@ -343,7 +339,7 @@ proc primary(self: Parser): Expression =
|
||||||
result = newYieldExpr(self.expression(), tok)
|
result = newYieldExpr(self.expression(), tok)
|
||||||
else:
|
else:
|
||||||
# Empty yield
|
# Empty yield
|
||||||
result = newYieldExpr(newNilExpr(Token()), tok)
|
result = newYieldExpr(nil, tok)
|
||||||
of Await:
|
of Await:
|
||||||
let tok = self.step()
|
let tok = self.step()
|
||||||
if self.currentFunction.isNil():
|
if self.currentFunction.isNil():
|
||||||
|
@ -364,8 +360,6 @@ proc primary(self: Parser): Expression =
|
||||||
result = newBinExpr(self.step())
|
result = newBinExpr(self.step())
|
||||||
of String:
|
of String:
|
||||||
result = newStrExpr(self.step())
|
result = newStrExpr(self.step())
|
||||||
of Infinity:
|
|
||||||
result = newInfExpr(self.step())
|
|
||||||
of Function:
|
of Function:
|
||||||
discard self.step()
|
discard self.step()
|
||||||
result = Expression(self.funDecl(isLambda=true))
|
result = Expression(self.funDecl(isLambda=true))
|
||||||
|
@ -375,9 +369,6 @@ proc primary(self: Parser): Expression =
|
||||||
of Generator:
|
of Generator:
|
||||||
discard self.step()
|
discard self.step()
|
||||||
result = Expression(self.funDecl(isGenerator=true, isLambda=true))
|
result = Expression(self.funDecl(isGenerator=true, isLambda=true))
|
||||||
of TokenType.Var:
|
|
||||||
discard self.step()
|
|
||||||
result = newVarExpr(self.expression(), self.peek(-1))
|
|
||||||
of TokenType.Ref:
|
of TokenType.Ref:
|
||||||
discard self.step()
|
discard self.step()
|
||||||
result = newRefExpr(self.expression(), self.peek(-1))
|
result = newRefExpr(self.expression(), self.peek(-1))
|
||||||
|
@ -654,7 +645,7 @@ proc yieldStmt(self: Parser): Statement =
|
||||||
if not self.check(Semicolon):
|
if not self.check(Semicolon):
|
||||||
result = newYieldStmt(self.expression(), tok)
|
result = newYieldStmt(self.expression(), tok)
|
||||||
else:
|
else:
|
||||||
result = newYieldStmt(newNilExpr(Token(lexeme: "nil")), tok)
|
result = newYieldStmt(nil, tok)
|
||||||
endOfLine("missing semicolon after 'yield'")
|
endOfLine("missing semicolon after 'yield'")
|
||||||
|
|
||||||
|
|
||||||
|
@ -857,7 +848,8 @@ proc parsePragmas(self: Parser): seq[Pragma] =
|
||||||
elif self.match("("):
|
elif self.match("("):
|
||||||
while not self.match(")") and not self.done():
|
while not self.match(")") and not self.done():
|
||||||
exp = self.primary()
|
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)
|
self.error("pragma arguments can only be literals", exp.token)
|
||||||
args.add(LiteralExpr(exp))
|
args.add(LiteralExpr(exp))
|
||||||
if not self.match(","):
|
if not self.match(","):
|
||||||
|
@ -865,7 +857,8 @@ proc parsePragmas(self: Parser): seq[Pragma] =
|
||||||
self.expect(LeftParen, "unterminated parenthesis in pragma arguments")
|
self.expect(LeftParen, "unterminated parenthesis in pragma arguments")
|
||||||
else:
|
else:
|
||||||
exp = self.primary()
|
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)
|
self.error("pragma arguments can only be literals", exp.token)
|
||||||
args.add(LiteralExpr(exp))
|
args.add(LiteralExpr(exp))
|
||||||
result.add(newPragma(name, args))
|
result.add(newPragma(name, args))
|
||||||
|
|
|
@ -9,30 +9,6 @@ fn clock*: float {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn print*(x: int) {
|
fn print*[T: Number | string | bool | nan | inf](x: T) {
|
||||||
#pragma[magic: "PrintInt64"]
|
#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"]
|
|
||||||
}
|
|
|
@ -1,23 +1,73 @@
|
||||||
# Stub type declarations for peon's intrinsic types
|
# Stub type declarations for peon's intrinsic types
|
||||||
|
|
||||||
|
|
||||||
type int64* = object {#pragma[magic: "int64"]}
|
type int64* = object {
|
||||||
type int32* = object {#pragma[magic: "int32"]}
|
#pragma[magic: "int64"]
|
||||||
type int16* = object {#pragma[magic: "int16"]}
|
}
|
||||||
type int8* = object {#pragma[magic: "int8"]}
|
|
||||||
type uint64* = object {#pragma[magic: "uint64"]}
|
type int32* = object {
|
||||||
type uint32* = object {#pragma[magic: "uint32"]}
|
#pragma[magic: "int32"]
|
||||||
type uint16* = object {#pragma[magic: "uint16"]}
|
}
|
||||||
type uint8* = object {#pragma[magic: "uint8"]}
|
|
||||||
type float64* = object {#pragma[magic: "float64"]}
|
type int16* = object {
|
||||||
type float32* = object {#pragma[magic: "float32"]}
|
#pragma[magic: "int16"]
|
||||||
type bool* = object {#pragma[magic: "bool"]}
|
}
|
||||||
type string* = object {#pragma[magic: "string"]}
|
|
||||||
type any* = object {#pragma[magic: "any"]}
|
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
|
# Some convenience aliases
|
||||||
type int* = int64;
|
type int* = int64;
|
||||||
type float* = float64;
|
type float* = float64;
|
||||||
type SignedInteger* = int64 | int32 | int16 | int8;
|
type SignedInteger* = int64 | int32 | int16 | int8;
|
||||||
type UnsignedInteger* = uint64 | uint32 | uint16 | uint8;
|
type UnsignedInteger* = uint64 | uint32 | uint16 | uint8;
|
||||||
type Integer* = SignedInteger | UnsignedInteger;
|
type Integer* = SignedInteger | UnsignedInteger;
|
||||||
|
|
|
@ -51,9 +51,6 @@ proc fillSymbolTable*(tokenizer: Lexer) =
|
||||||
# but we don't need to care about that until
|
# but we don't need to care about that until
|
||||||
# we're in the parsing/compilation steps so
|
# we're in the parsing/compilation steps so
|
||||||
# it's fine
|
# 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("true", True)
|
||||||
tokenizer.symbols.addKeyword("false", False)
|
tokenizer.symbols.addKeyword("false", False)
|
||||||
tokenizer.symbols.addKeyword("ref", TokenType.Ref)
|
tokenizer.symbols.addKeyword("ref", TokenType.Ref)
|
||||||
|
|
|
@ -19,4 +19,4 @@ fn fooBar(a, b: int): int {
|
||||||
|
|
||||||
|
|
||||||
noReturn(1);
|
noReturn(1);
|
||||||
print(fooBar(1, 3) == 1); # true
|
print(fooBar(1, 3) == 1); # true
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Another test for generic functions
|
# A test for generic functions
|
||||||
import std;
|
import std;
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,4 +9,4 @@ fn sum[T: int | int32](a, b: T): T {
|
||||||
|
|
||||||
print(sum(1, 2)); # Prints 3
|
print(sum(1, 2)); # Prints 3
|
||||||
print(sum(1'i32, 2'i32)); # Also 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
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
# Tests more stuff about generics. This test should fail to compile
|
# Tests more stuff about generics. This test should fail to compile
|
||||||
|
import std;
|
||||||
|
|
||||||
|
|
||||||
fn identity(x: int32): int32 {
|
fn identity(x: int32): int32 {
|
||||||
return x;
|
return x;
|
||||||
|
|
Loading…
Reference in New Issue