3ae8c60ebb
- Fix lirValToC crash on lvkInt in hStore raw C emission - Add hAlloca handling to lowerExpr (returns &name, avoids unhandled fallback) - Fix nested comment syntax in unhandled expr fallback - Rewrite buildLval to handle hIndexPtr and nested hFieldPtr/hArrowField so assignments like arr[i].field = val emit direct C lvalues - Make &&/|| temporaries unique (__and_tmp_N/__or_tmp_N) to avoid duplicate declarations in the same function - Selfhost null-deref fix in sema.bux (unchained nested conditions)
229 lines
6.6 KiB
Nim
229 lines
6.6 KiB
Nim
import ast, types, token, source_location
|
|
|
|
type
|
|
HirKind* = enum
|
|
# Literals
|
|
hLit
|
|
hVar
|
|
hSelf
|
|
# Operations
|
|
hUnary
|
|
hBinary
|
|
hAssign
|
|
# Control flow
|
|
hIf
|
|
hWhile
|
|
hLoop
|
|
hBreak
|
|
hContinue
|
|
hReturn
|
|
# Memory
|
|
hAlloca
|
|
hLoad
|
|
hStore
|
|
hFieldPtr
|
|
hArrowField
|
|
hIndexPtr
|
|
hSliceIndex
|
|
# Functions
|
|
hCall
|
|
hCallIndirect
|
|
# Type operations
|
|
hCast
|
|
hIs
|
|
hSizeOf
|
|
# Concurrency
|
|
hSpawn
|
|
# Compile-time code generation
|
|
hEmit
|
|
# Trait objects (dynamic dispatch)
|
|
hDynRef
|
|
hDynCall
|
|
# Composite
|
|
hBlock
|
|
hStructInit
|
|
hSliceInit
|
|
hRange
|
|
hTupleInit
|
|
# Match (desugared to switch/branch later)
|
|
hMatch
|
|
|
|
HirNode* = ref object
|
|
loc*: SourceLocation
|
|
typ*: Type
|
|
case kind*: HirKind
|
|
of hLit:
|
|
litToken*: Token
|
|
of hVar:
|
|
varName*: string
|
|
of hSelf:
|
|
discard
|
|
of hUnary:
|
|
unaryOp*: TokenKind
|
|
unaryOperand*: HirNode
|
|
of hBinary:
|
|
binaryOp*: TokenKind
|
|
binaryLeft*: HirNode
|
|
binaryRight*: HirNode
|
|
of hAssign:
|
|
assignOp*: TokenKind
|
|
assignTarget*: HirNode
|
|
assignValue*: HirNode
|
|
of hIf:
|
|
ifCond*: HirNode
|
|
ifThen*: HirNode
|
|
ifElse*: HirNode
|
|
of hWhile:
|
|
whileCond*: HirNode
|
|
whileBody*: HirNode
|
|
of hLoop:
|
|
loopBody*: HirNode
|
|
of hBreak:
|
|
breakLabel*: string
|
|
of hContinue:
|
|
continueLabel*: string
|
|
of hReturn:
|
|
returnValue*: HirNode
|
|
of hAlloca:
|
|
allocaType*: Type
|
|
allocaName*: string
|
|
of hLoad:
|
|
loadPtr*: HirNode
|
|
of hStore:
|
|
storePtr*: HirNode
|
|
storeValue*: HirNode
|
|
of hFieldPtr:
|
|
fieldPtrBase*: HirNode
|
|
fieldName*: string
|
|
of hArrowField:
|
|
arrowFieldBase*: HirNode
|
|
arrowFieldName*: string
|
|
of hIndexPtr:
|
|
indexPtrBase*: HirNode
|
|
indexPtrIndex*: HirNode
|
|
of hCall:
|
|
callCallee*: string
|
|
callArgs*: seq[HirNode]
|
|
of hCallIndirect:
|
|
callIndirectCallee*: HirNode
|
|
callIndirectArgs*: seq[HirNode]
|
|
of hCast:
|
|
castOperand*: HirNode
|
|
castType*: Type
|
|
of hIs:
|
|
isOperand*: HirNode
|
|
isType*: Type
|
|
of hSizeOf:
|
|
sizeOfType*: Type
|
|
of hSpawn:
|
|
spawnCallee*: string
|
|
spawnArgs*: seq[HirNode]
|
|
spawnAsync*: bool
|
|
of hEmit:
|
|
emitCode*: string
|
|
of hDynRef:
|
|
dynRefData*: HirNode
|
|
dynRefInterface*: string
|
|
dynRefConcreteType*: string
|
|
of hDynCall:
|
|
dynCallReceiver*: HirNode
|
|
dynCallMethod*: string
|
|
dynCallArgs*: seq[HirNode]
|
|
of hBlock:
|
|
blockStmts*: seq[HirNode]
|
|
blockExpr*: HirNode
|
|
isScope*: bool
|
|
of hStructInit:
|
|
structInitName*: string
|
|
structInitFields*: seq[tuple[name: string, value: HirNode]]
|
|
of hSliceInit:
|
|
sliceInitElements*: seq[HirNode]
|
|
sliceInitLen*: int
|
|
of hSliceIndex:
|
|
sliceIndexBase*: HirNode
|
|
sliceIndexIndex*: HirNode
|
|
sliceIndexBoundsCheck*: bool
|
|
of hRange:
|
|
rangeLo*: HirNode
|
|
rangeHi*: HirNode
|
|
rangeInclusive*: bool
|
|
of hTupleInit:
|
|
tupleInitElements*: seq[HirNode]
|
|
of hMatch:
|
|
matchSubject*: HirNode
|
|
matchArms*: seq[HirMatchArm]
|
|
|
|
HirMatchArm* = object
|
|
pattern*: Pattern
|
|
body*: HirNode
|
|
|
|
HirFunc* = object
|
|
name*: string
|
|
params*: seq[tuple[name: string, typ: Type]]
|
|
retType*: Type
|
|
body*: HirNode
|
|
isPublic*: bool
|
|
|
|
HirEnumVariant* = object
|
|
name*: string
|
|
fields*: seq[Type] # Positional fields for algebraic enums
|
|
namedFields*: seq[tuple[name: string, typ: Type]] # Named fields
|
|
|
|
HirModule* = object
|
|
funcs*: seq[HirFunc]
|
|
externFuncs*: seq[HirFunc] # Functions declared with extern (no body)
|
|
structs*: seq[tuple[name: string, fields: seq[tuple[name: string, typ: Type]]]]
|
|
enums*: seq[tuple[name: string, variants: seq[HirEnumVariant]]]
|
|
consts*: seq[tuple[name: string, typ: Type, value: HirNode]]
|
|
interfaces*: seq[tuple[name: string, hasAssocTypes: bool, methods: seq[tuple[name: string, params: seq[Type], ret: Type]]]]
|
|
vtables*: seq[tuple[interfaceName: string, concreteType: string, methodNames: seq[string], hasAssocTypes: bool]]
|
|
|
|
# Constructor helpers
|
|
proc hirLit*(tok: Token, typ: Type, loc: SourceLocation): HirNode =
|
|
HirNode(kind: hLit, litToken: tok, typ: typ, loc: loc)
|
|
|
|
proc hirVar*(name: string, typ: Type, loc: SourceLocation): HirNode =
|
|
HirNode(kind: hVar, varName: name, typ: typ, loc: loc)
|
|
|
|
proc hirSelf*(typ: Type, loc: SourceLocation): HirNode =
|
|
HirNode(kind: hSelf, typ: typ, loc: loc)
|
|
|
|
proc hirUnary*(op: TokenKind, operand: HirNode, typ: Type, loc: SourceLocation): HirNode =
|
|
HirNode(kind: hUnary, unaryOp: op, unaryOperand: operand, typ: typ, loc: loc)
|
|
|
|
proc hirBinary*(op: TokenKind, left, right: HirNode, typ: Type, loc: SourceLocation): HirNode =
|
|
HirNode(kind: hBinary, binaryOp: op, binaryLeft: left, binaryRight: right, typ: typ, loc: loc)
|
|
|
|
proc hirCall*(callee: string, args: seq[HirNode], typ: Type, loc: SourceLocation): HirNode =
|
|
HirNode(kind: hCall, callCallee: callee, callArgs: args, typ: typ, loc: loc)
|
|
|
|
proc hirReturn*(value: HirNode, loc: SourceLocation): HirNode =
|
|
HirNode(kind: hReturn, returnValue: value, typ: makeVoid(), loc: loc)
|
|
|
|
proc hirBlock*(stmts: seq[HirNode], expr: HirNode, typ: Type, loc: SourceLocation, isScope: bool = false): HirNode =
|
|
HirNode(kind: hBlock, blockStmts: stmts, blockExpr: expr, typ: typ, loc: loc, isScope: isScope)
|
|
|
|
proc hirIf*(cond, thenBranch, elseBranch: HirNode, loc: SourceLocation): HirNode =
|
|
HirNode(kind: hIf, ifCond: cond, ifThen: thenBranch, ifElse: elseBranch, typ: makeVoid(), loc: loc)
|
|
|
|
|
|
proc hirAlloca*(name: string, typ: Type, loc: SourceLocation): HirNode =
|
|
HirNode(kind: hAlloca, allocaType: typ, allocaName: name, typ: makePointer(typ), loc: loc)
|
|
|
|
proc hirStore*(ptrNode, value: HirNode, loc: SourceLocation): HirNode =
|
|
HirNode(kind: hStore, storePtr: ptrNode, storeValue: value, typ: makeVoid(), loc: loc)
|
|
|
|
proc hirLoad*(ptrNode: HirNode, typ: Type, loc: SourceLocation): HirNode =
|
|
HirNode(kind: hLoad, loadPtr: ptrNode, typ: typ, loc: loc)
|
|
|
|
proc hirEmit*(code: string, loc: SourceLocation): HirNode =
|
|
HirNode(kind: hEmit, emitCode: code, typ: makeVoid(), loc: loc)
|
|
|
|
proc hirDynRef*(data: HirNode, interfaceName, concreteType: string, loc: SourceLocation): HirNode =
|
|
HirNode(kind: hDynRef, dynRefData: data, dynRefInterface: interfaceName,
|
|
dynRefConcreteType: concreteType, typ: makeDynRef(interfaceName), loc: loc)
|
|
|
|
proc hirDynCall*(receiver: HirNode, methodName: string, args: seq[HirNode], typ: Type, loc: SourceLocation): HirNode =
|
|
HirNode(kind: hDynCall, dynCallReceiver: receiver, dynCallMethod: methodName,
|
|
dynCallArgs: args, typ: typ, loc: loc)
|