303 lines
9.0 KiB
Nim
303 lines
9.0 KiB
Nim
import errors
|
|
import frontend/parsing/parser
|
|
|
|
|
|
import std/tables
|
|
|
|
|
|
export ast, errors
|
|
|
|
|
|
|
|
type
|
|
IntegerSize* = enum
|
|
## Integer size enumeration
|
|
Tiny = 8
|
|
Short = 16
|
|
Long = 32
|
|
LongLong = 64
|
|
|
|
FloatSize* = enum
|
|
## Float size enumeration
|
|
Half = 32
|
|
Full = 64
|
|
|
|
TypeKind* = enum
|
|
## Enumeration of compile-time types
|
|
Integer,
|
|
Float,
|
|
String,
|
|
NaN,
|
|
Infinity,
|
|
Boolean,
|
|
Any,
|
|
Typevar,
|
|
Auto,
|
|
Byte,
|
|
Char,
|
|
Structure,
|
|
EnumEntry,
|
|
Reference,
|
|
Pointer,
|
|
Union,
|
|
Function,
|
|
Lent,
|
|
Const,
|
|
Generic
|
|
|
|
|
|
Type* = ref object
|
|
## A compile-time type
|
|
|
|
# Is this a type constant?
|
|
constant*: bool
|
|
# Can it be mutated?
|
|
mutable*: bool
|
|
# Is it a compiler intrinsic?
|
|
intrinsic*: bool
|
|
# Mapping of generic names to types
|
|
genericTypes*: TableRef[string, Type]
|
|
genericValues*: TableRef[string, Type]
|
|
# Type pragmas
|
|
pragmas*: TableRef[string, Pragma]
|
|
case kind*: TypeKind
|
|
of Integer:
|
|
signed*: bool
|
|
size*: IntegerSize
|
|
of Float:
|
|
width*: FloatSize
|
|
of Infinity:
|
|
positive*: bool
|
|
of Function:
|
|
isLambda*: bool
|
|
isGenerator*: bool
|
|
isCoroutine*: bool
|
|
isAuto*: bool
|
|
signature*: TypeSignature
|
|
returnType*: Type
|
|
unsafe*: bool
|
|
isBuiltin*: bool
|
|
builtinOp*: string
|
|
of Typevar:
|
|
wrapped*: Type
|
|
of Structure:
|
|
name*: string
|
|
fields*: TableRef[string, Type]
|
|
parent*: Type
|
|
interfaces*: seq[Type]
|
|
isEnum*: bool
|
|
of Reference, Pointer, Lent, Const:
|
|
value*: Type
|
|
of Generic, Union:
|
|
types*: seq[tuple[match: bool, kind: Type, value: Expression]]
|
|
else:
|
|
discard
|
|
|
|
WarningKind* {.pure.} = enum
|
|
## A warning enumeration type
|
|
UserWarning
|
|
|
|
NameKind* {.pure.} = enum
|
|
## A name enumeration type
|
|
Default, Var, Module
|
|
|
|
Name* = ref object
|
|
## A generic name object
|
|
|
|
# Type of the identifier (NOT of the value!)
|
|
case kind*: NameKind
|
|
of Module:
|
|
path*: string
|
|
# Full absolute path of the module,
|
|
# including the extension
|
|
absPath*: string
|
|
# Just for easier lookup, it's all
|
|
# pointers anyway
|
|
names*: TableRef[string, Name]
|
|
else:
|
|
discard
|
|
# The name's identifier
|
|
ident*: IdentExpr
|
|
# Owner of the identifier (module)
|
|
module*: Name
|
|
# File where the name is declared
|
|
file*: string
|
|
# Scope depth
|
|
depth*: int
|
|
# Is this name private?
|
|
isPrivate*: bool
|
|
# The type of the name's associated
|
|
# value
|
|
valueType*: Type
|
|
# The function that "owns" this name (may be nil!)
|
|
owner*: Name
|
|
# Where is this node declared in its file?
|
|
line*: int
|
|
# The AST node associated with this node. This
|
|
# is needed because we tyoecheck function and type
|
|
# declarations only if, and when, they're actually
|
|
# used
|
|
node*: Declaration
|
|
# Who is this name exported to? (Only makes sense if isPrivate
|
|
# equals false)
|
|
exportedTo*: seq[Name]
|
|
|
|
TypeSignature* = seq[tuple[name: string, kind: Type, default: TypedExpr]]
|
|
|
|
## Our typed AST representation
|
|
|
|
TypedNode* = ref object of RootObj
|
|
## A generic typed AST node
|
|
node*: ASTNode
|
|
|
|
TypedExpr* = ref object of TypedNode
|
|
## A generic typed expression
|
|
kind*: Type
|
|
|
|
TypedUnaryExpr* = ref object of TypedExpr
|
|
## A generic typed unary expression
|
|
a*: TypedExpr
|
|
|
|
TypedBinaryExpr* = ref object of TypedUnaryExpr
|
|
## A generic typed binary expression
|
|
b*: TypedExpr
|
|
|
|
TypedIdentExpr* = ref object of TypedExpr
|
|
## A typed identifier expression
|
|
name*: Name
|
|
|
|
TypedCallExpr* = ref object of TypedExpr
|
|
## A typed function call expression
|
|
callee*: Name
|
|
args*: TypeSignature
|
|
|
|
TypedDecl* = ref object of TypedNode
|
|
## A typed declaration node
|
|
name*: Name # The declaration's name object
|
|
|
|
TypedVarDecl* = ref object of TypedDecl
|
|
## A typed variable declaration node
|
|
init*: TypedExpr
|
|
|
|
TypedTypeDecl* = ref object of TypedDecl
|
|
## A typed type declaration node
|
|
fields*: TableRef[string, TypedExpr]
|
|
parent*: Name
|
|
interfaces*: seq[TypedTypeDecl]
|
|
|
|
TypedEnumDecl* = ref object of TypedTypeDecl
|
|
## A typed enum declaration node
|
|
enumeration*: Type
|
|
variants: seq[TypedTypeDecl]
|
|
|
|
TypedFunDecl* = ref object of TypedDecl
|
|
## A typed function declaration
|
|
args*: seq[tuple[name: Name, default: TypedExpr]]
|
|
body*: TypedBlockStmt
|
|
|
|
TypedStmt* = ref object of TypedNode
|
|
## A typed statement node
|
|
|
|
TypedExprStmt* = ref object of TypedStmt
|
|
expression*: TypedExpr
|
|
|
|
TypedBlockStmt* = ref object of TypedStmt
|
|
## A typed block statement
|
|
body*: seq[TypedNode]
|
|
|
|
TypedIfStmt* = ref object of TypedStmt
|
|
## A typed if statement node
|
|
thenBranch*: TypedBlockStmt
|
|
elseBranch*: TypedBlockStmt
|
|
condition*: TypedExpr
|
|
|
|
TypedWhileStmt* = ref object of TypedStmt
|
|
## A typed while statement node
|
|
body*: TypedBlockStmt
|
|
condition*: TypedExpr
|
|
|
|
|
|
proc newTypedNode*(node: ASTNode): TypedNode =
|
|
## Initializes a new typed node
|
|
new(result)
|
|
result.node = node
|
|
|
|
|
|
proc newTypedExpr*(node: Expression, kind: Type): TypedExpr =
|
|
## Initializes a new typed expression
|
|
result = TypedExpr(node: node, kind: kind)
|
|
|
|
|
|
proc newTypedDecl*(node: Declaration, name: Name): TypedDecl =
|
|
## Initializes a new typed declaration
|
|
result = TypedDecl(node: node, name: name)
|
|
|
|
|
|
proc newTypedTypeDecl*(node: TypeDecl, name: Name, fields: TableRef[string, TypedExpr], parent: Name): TypedTypeDecl =
|
|
## Initializes a new typed function declaration
|
|
result = TypedTypeDecl(node: node, name: name, fields: fields, parent: parent)
|
|
|
|
|
|
proc newTypedEnumDecl*(node: TypeDecl, name: Name, variants: seq[TypedTypeDecl], enumeration: Type): TypedEnumDecl =
|
|
## Initializes a new typed function declaration
|
|
result = TypedEnumDecl(node: node, name: name, variants: variants, enumeration: enumeration)
|
|
|
|
|
|
proc newTypedFunDecl*(node: FunDecl, name: Name, body: TypedBlockStmt): TypedFunDecl =
|
|
## Initializes a new typed function declaration
|
|
result = TypedFunDecl(node: node, name: name, body: body)
|
|
|
|
|
|
proc newTypedVarDecl*(node: VarDecl, name: Name, init: TypedExpr): TypedVarDecl =
|
|
## Initializes a new typed function declaration
|
|
result = TypedVarDecl(node: node, name: name, init: init)
|
|
|
|
|
|
proc newTypedIdentExpr*(node: IdentExpr, name: Name): TypedIdentExpr =
|
|
## Initializes a new typed identifier expression
|
|
result = TypedIdentExpr(node: node, name: name, kind: name.valueType)
|
|
|
|
|
|
proc newTypedUnaryExpr*(node: UnaryExpr, kind: Type, a: TypedExpr): TypedUnaryExpr =
|
|
## Initializes a new typed unary expression
|
|
result = TypedUnaryExpr(node: node, a: a, kind: kind)
|
|
|
|
|
|
proc newTypedBinaryExpr*(node: UnaryExpr, kind: Type, a, b: TypedExpr): TypedBinaryExpr =
|
|
## Initializes a new typed binary expression
|
|
result = TypedBinaryExpr(node: node, a: a, b: b, kind: kind)
|
|
|
|
|
|
proc newTypedCallExpr*(node: CallExpr, callee: Name,
|
|
args: TypeSignature): TypedCallExpr =
|
|
## Initializes a new typed function call expression
|
|
result = TypedCallExpr(node: node, callee: callee, args: args, kind: callee.valueType.returnType)
|
|
|
|
|
|
proc newTypedBlockStmt*(node: BlockStmt, body: seq[TypedNode]): TypedBlockStmt =
|
|
## Initializes a new typed block statement
|
|
result = TypedBlockStmt(node: node, body: body)
|
|
|
|
|
|
proc newTypedWhileStmt*(node: WhileStmt, body: TypedBlockStmt, condition: TypedExpr): TypedWhileStmt =
|
|
## Initializes a new typed while statement
|
|
result = TypedWhileStmt(node: node, body: body, condition: condition)
|
|
|
|
|
|
proc newTypedIfStmt*(node: IfStmt, thenBranch, elseBranch: TypedBlockStmt, condition: TypedExpr): TypedIfStmt =
|
|
## Initializes a new typed block statement
|
|
result = TypedIfStmt(node: node, thenBranch: thenBranch,
|
|
elseBranch: elseBranch, condition: condition)
|
|
|
|
|
|
proc getName*(self: TypedNode): Name =
|
|
## Gets the name object associated with the
|
|
## given typed node, if it has any
|
|
case self.node.kind:
|
|
of identExpr:
|
|
result = TypedIdentExpr(self).name
|
|
of NodeKind.funDecl, NodeKind.varDecl, NodeKind.typeDecl:
|
|
result = TypedDecl(self).name
|
|
else:
|
|
result = nil # TODO
|