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.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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -24,9 +24,6 @@ type
|
|||
# Booleans
|
||||
True, False,
|
||||
|
||||
# Other singleton types
|
||||
Infinity, NotANumber, Nil
|
||||
|
||||
# Control flow statements
|
||||
If, Else,
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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"]
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -19,4 +19,4 @@ fn fooBar(a, b: int): int {
|
|||
|
||||
|
||||
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;
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
# Tests more stuff about generics. This test should fail to compile
|
||||
import std;
|
||||
|
||||
|
||||
fn identity(x: int32): int32 {
|
||||
return x;
|
||||
|
|
Loading…
Reference in New Issue