Fixed issue with self-referencing variable declarations
This commit is contained in:
parent
ace04ee34c
commit
d1d5c10e49
|
@ -616,7 +616,7 @@ method infer*(self: Compiler, node: LiteralExpr): Type =
|
||||||
discard # Unreachable
|
discard # Unreachable
|
||||||
|
|
||||||
|
|
||||||
method infer*(self: Compiler, node: Expression): Type =
|
method infer*(self: Compiler, node: Expression): Type =
|
||||||
## Infers the type of a given expression and
|
## Infers the type of a given expression and
|
||||||
## returns it
|
## returns it
|
||||||
if node.isNil():
|
if node.isNil():
|
||||||
|
@ -1008,7 +1008,8 @@ proc declare*(self: Compiler, node: ASTNode): Name {.discardable.} =
|
||||||
line: node.token.line,
|
line: node.token.line,
|
||||||
isPrivate: node.isPrivate,
|
isPrivate: node.isPrivate,
|
||||||
isReal: true,
|
isReal: true,
|
||||||
belongsTo: self.currentFunction
|
belongsTo: self.currentFunction,
|
||||||
|
valueType: Type(kind: CustomType)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
n = self.names[^1]
|
n = self.names[^1]
|
||||||
|
|
|
@ -94,7 +94,7 @@ proc compile*(self: BytecodeCompiler, ast: seq[Declaration], file: string, lines
|
||||||
mode: CompileMode = Debug): Chunk
|
mode: CompileMode = Debug): Chunk
|
||||||
proc statement(self: BytecodeCompiler, node: Statement)
|
proc statement(self: BytecodeCompiler, node: Statement)
|
||||||
proc declaration(self: BytecodeCompiler, node: Declaration)
|
proc declaration(self: BytecodeCompiler, node: Declaration)
|
||||||
proc varDecl(self: BytecodeCompiler, node: VarDecl, name: Name)
|
proc varDecl(self: BytecodeCompiler, node: VarDecl)
|
||||||
proc specialize(self: BytecodeCompiler, typ: Type, args: seq[Expression]): Type {.discardable.}
|
proc specialize(self: BytecodeCompiler, typ: Type, args: seq[Expression]): Type {.discardable.}
|
||||||
proc patchReturnAddress(self: BytecodeCompiler, pos: int)
|
proc patchReturnAddress(self: BytecodeCompiler, pos: int)
|
||||||
proc handleMagicPragma(self: BytecodeCompiler, pragma: Pragma, name: Name)
|
proc handleMagicPragma(self: BytecodeCompiler, pragma: Pragma, name: Name)
|
||||||
|
@ -1194,19 +1194,22 @@ method identifier(self: BytecodeCompiler, node: IdentExpr, name: Name = nil, com
|
||||||
return nil
|
return nil
|
||||||
result = s.valueType
|
result = s.valueType
|
||||||
if not compile:
|
if not compile:
|
||||||
return
|
return result
|
||||||
var node = s.ident
|
var node = s.ident
|
||||||
if s.isConst:
|
if s.isConst:
|
||||||
# Constants are always emitted as Load* instructions
|
# Constants are always emitted as Load* instructions
|
||||||
# no matter the scope depth
|
# no matter the scope depth
|
||||||
self.emitConstant(VarDecl(s.node).value, self.infer(node))
|
if strict:
|
||||||
|
self.emitConstant(VarDecl(s.node).value, self.inferOrError(node))
|
||||||
|
else:
|
||||||
|
self.emitConstant(VarDecl(s.node).value, self.infer(node))
|
||||||
elif s.kind == NameKind.Function:
|
elif s.kind == NameKind.Function:
|
||||||
# Functions have no runtime representation, they're just
|
# Functions have no runtime representation, they're just
|
||||||
# a location to jump to, but we pretend they aren't and
|
# a location to jump to, but we pretend they aren't and
|
||||||
# resolve them to their address into our bytecode when
|
# resolve them to their address into our bytecode when
|
||||||
# they're referenced
|
# they're referenced
|
||||||
self.emitByte(LoadUInt64, node.token.line)
|
self.emitByte(LoadUInt64, node.token.line)
|
||||||
self.emitBytes(self.chunk.writeConstant(s.valueType.location.toLong()), node.token.line)
|
self.emitBytes(self.chunk.writeConstant(s.codePos.toLong()), node.token.line)
|
||||||
elif s.isBuiltin:
|
elif s.isBuiltin:
|
||||||
case s.ident.token.lexeme:
|
case s.ident.token.lexeme:
|
||||||
of "nil":
|
of "nil":
|
||||||
|
@ -1782,7 +1785,7 @@ proc statement(self: BytecodeCompiler, node: Statement) =
|
||||||
self.expression(Expression(node))
|
self.expression(Expression(node))
|
||||||
|
|
||||||
|
|
||||||
proc varDecl(self: BytecodeCompiler, node: VarDecl, name: Name) =
|
proc varDecl(self: BytecodeCompiler, node: VarDecl) =
|
||||||
## Compiles variable declarations
|
## Compiles variable declarations
|
||||||
var typ: Type
|
var typ: Type
|
||||||
# Our parser guarantees that the variable declaration
|
# Our parser guarantees that the variable declaration
|
||||||
|
@ -1793,7 +1796,7 @@ proc varDecl(self: BytecodeCompiler, node: VarDecl, name: Name) =
|
||||||
typ = self.inferOrError(node.valueType)
|
typ = self.inferOrError(node.valueType)
|
||||||
if typ.kind == Auto:
|
if typ.kind == Auto:
|
||||||
self.error("automatic types require initialization", node)
|
self.error("automatic types require initialization", node)
|
||||||
elif node.valueType.isNil:
|
elif node.valueType.isNil():
|
||||||
# Variable has no type declaration: the type
|
# Variable has no type declaration: the type
|
||||||
# of its value takes over
|
# of its value takes over
|
||||||
typ = self.inferOrError(node.value)
|
typ = self.inferOrError(node.value)
|
||||||
|
@ -1811,6 +1814,12 @@ proc varDecl(self: BytecodeCompiler, node: VarDecl, name: Name) =
|
||||||
self.expression(node.value)
|
self.expression(node.value)
|
||||||
self.emitByte(AddVar, node.token.line)
|
self.emitByte(AddVar, node.token.line)
|
||||||
inc(self.stackIndex)
|
inc(self.stackIndex)
|
||||||
|
# We declare the name only now in order to make
|
||||||
|
# sure that stuff like var n = n; works as expected.
|
||||||
|
# If we declared it early, we'd have a duplicate with
|
||||||
|
# no type that would shadow the original value, which
|
||||||
|
# is no good
|
||||||
|
var name = self.declare(node)
|
||||||
name.position = self.stackIndex
|
name.position = self.stackIndex
|
||||||
name.valueType = typ
|
name.valueType = typ
|
||||||
|
|
||||||
|
@ -1909,6 +1918,13 @@ proc funDecl(self: BytecodeCompiler, node: FunDecl, name: Name) =
|
||||||
self.stackIndex = stackIdx
|
self.stackIndex = stackIdx
|
||||||
|
|
||||||
|
|
||||||
|
proc typeDecl(self: BytecodeCompiler, node: TypeDecl, name: Name) =
|
||||||
|
## Compiles type declarations
|
||||||
|
for field in node.fields:
|
||||||
|
if self.compare(self.inferOrError(field.valueType), name.valueType) and not node.isRef:
|
||||||
|
self.error(&"illegal type recursion for non-ref type '{name.ident.token.lexeme}'")
|
||||||
|
|
||||||
|
|
||||||
proc declaration(self: BytecodeCompiler, node: Declaration) =
|
proc declaration(self: BytecodeCompiler, node: Declaration) =
|
||||||
## Compiles declarations, statements and expressions
|
## Compiles declarations, statements and expressions
|
||||||
## recursively
|
## recursively
|
||||||
|
@ -1941,11 +1957,9 @@ proc declaration(self: BytecodeCompiler, node: Declaration) =
|
||||||
if not name.valueType.returnType.isNil() and name.valueType.returnType.kind == Generic:
|
if not name.valueType.returnType.isNil() and name.valueType.returnType.kind == Generic:
|
||||||
name.valueType.returnType.asUnion = true
|
name.valueType.returnType.asUnion = true
|
||||||
of NodeKind.typeDecl:
|
of NodeKind.typeDecl:
|
||||||
# Custom types don't do much other than
|
self.typeDecl(TypeDecl(node), self.declare(node))
|
||||||
# declaring a name in the given scope
|
|
||||||
self.declare(node)
|
|
||||||
of NodeKind.varDecl:
|
of NodeKind.varDecl:
|
||||||
self.varDecl(VarDecl(node), self.declare(node))
|
self.varDecl(VarDecl(node))
|
||||||
else:
|
else:
|
||||||
self.statement(Statement(node))
|
self.statement(Statement(node))
|
||||||
|
|
||||||
|
|
|
@ -757,7 +757,7 @@ proc `$`*(self: ASTNode): string =
|
||||||
result &= &"""FunDecl(name={self.name}, body={self.body}, type={self.returnType}, arguments=[{self.arguments.join(", ")}], defaults=[{self.defaults.join(", ")}], generics=[{self.generics.join(", ")}], async={self.isAsync}, generator={self.isGenerator}, template={self.isTemplate}, private={self.isPrivate}, pragmas={self.pragmas})"""
|
result &= &"""FunDecl(name={self.name}, body={self.body}, type={self.returnType}, arguments=[{self.arguments.join(", ")}], defaults=[{self.defaults.join(", ")}], generics=[{self.generics.join(", ")}], async={self.isAsync}, generator={self.isGenerator}, template={self.isTemplate}, private={self.isPrivate}, pragmas={self.pragmas})"""
|
||||||
of typeDecl:
|
of typeDecl:
|
||||||
var self = TypeDecl(self)
|
var self = TypeDecl(self)
|
||||||
result &= &"""TypeDecl(name={self.name}, fields={self.fields}, defaults={self.defaults}, private={self.isPrivate}, pragmas={self.pragmas}, generics={self.generics}, parent={self.parent}, ref={self.isRef}, enum={self.isEnum})"""
|
result &= &"""TypeDecl(name={self.name}, fields={self.fields}, defaults={self.defaults}, private={self.isPrivate}, pragmas={self.pragmas}, generics={self.generics}, parent={self.parent}, ref={self.isRef}, enum={self.isEnum}, value={self.value})"""
|
||||||
of lambdaExpr:
|
of lambdaExpr:
|
||||||
var self = LambdaExpr(self)
|
var self = LambdaExpr(self)
|
||||||
result &= &"""Lambda(body={self.body}, type={self.returnType}, arguments=[{self.arguments.join(", ")}], defaults=[{self.defaults.join(", ")}], generator={self.isGenerator}, async={self.isAsync}, pragmas={self.pragmas})"""
|
result &= &"""Lambda(body={self.body}, type={self.returnType}, arguments=[{self.arguments.join(", ")}], defaults=[{self.defaults.join(", ")}], generator={self.isGenerator}, async={self.isAsync}, pragmas={self.pragmas})"""
|
||||||
|
|
Loading…
Reference in New Issue