symbol pre-resolution
This commit is contained in:
parent
3d07d010dc
commit
6575b077fe
@ -354,6 +354,8 @@ func (fp *FunctionParameter) Pos() Position { return fp.Position }
|
|||||||
// Identifier represents variable references and names.
|
// Identifier represents variable references and names.
|
||||||
type Identifier struct {
|
type Identifier struct {
|
||||||
Value string
|
Value string
|
||||||
|
ScopeDepth int // 0 = global, 1+ = local depth
|
||||||
|
SlotIndex int // register/stack slot (-1 = unresolved)
|
||||||
typeInfo TypeInfo
|
typeInfo TypeInfo
|
||||||
Position Position
|
Position Position
|
||||||
}
|
}
|
||||||
@ -367,6 +369,7 @@ func (i *Identifier) TypeInfo() TypeInfo {
|
|||||||
return i.typeInfo
|
return i.typeInfo
|
||||||
}
|
}
|
||||||
func (i *Identifier) Pos() Position { return i.Position }
|
func (i *Identifier) Pos() Position { return i.Position }
|
||||||
|
func (i *Identifier) IsResolved() bool { return i.SlotIndex >= 0 }
|
||||||
|
|
||||||
// NumberLiteral represents numeric constants including integers, floats, hex, and binary.
|
// NumberLiteral represents numeric constants including integers, floats, hex, and binary.
|
||||||
type NumberLiteral struct {
|
type NumberLiteral struct {
|
||||||
@ -422,6 +425,9 @@ type FunctionLiteral struct {
|
|||||||
Body []Statement
|
Body []Statement
|
||||||
ReturnType TypeInfo
|
ReturnType TypeInfo
|
||||||
Variadic bool
|
Variadic bool
|
||||||
|
LocalCount int // Pre-computed local variable count
|
||||||
|
UpvalueCount int // Number of captured variables
|
||||||
|
MaxStackDepth int // Maximum expression evaluation depth
|
||||||
Position Position
|
Position Position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
154
parser/parser.go
154
parser/parser.go
@ -31,9 +31,11 @@ type Parser struct {
|
|||||||
|
|
||||||
errors []ParseError
|
errors []ParseError
|
||||||
|
|
||||||
// Scope tracking
|
// Scope tracking with slot management
|
||||||
scopes []map[string]bool
|
scopes []map[string]*Variable
|
||||||
scopeTypes []string
|
scopeTypes []string
|
||||||
|
scopeSlots []int // Next available slot per scope
|
||||||
|
currentDepth int
|
||||||
|
|
||||||
// Struct tracking with ID mapping
|
// Struct tracking with ID mapping
|
||||||
structs map[string]*StructStatement
|
structs map[string]*StructStatement
|
||||||
@ -41,13 +43,23 @@ type Parser struct {
|
|||||||
nextID uint16
|
nextID uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Variable represents a resolved variable in scope
|
||||||
|
type Variable struct {
|
||||||
|
Name string
|
||||||
|
ScopeDepth int
|
||||||
|
SlotIndex int
|
||||||
|
TypeHint TypeInfo
|
||||||
|
}
|
||||||
|
|
||||||
// NewParser creates a new parser instance
|
// NewParser creates a new parser instance
|
||||||
func NewParser(lexer *Lexer) *Parser {
|
func NewParser(lexer *Lexer) *Parser {
|
||||||
p := &Parser{
|
p := &Parser{
|
||||||
lexer: lexer,
|
lexer: lexer,
|
||||||
errors: []ParseError{},
|
errors: []ParseError{},
|
||||||
scopes: []map[string]bool{make(map[string]bool)},
|
scopes: []map[string]*Variable{make(map[string]*Variable)},
|
||||||
scopeTypes: []string{"global"},
|
scopeTypes: []string{"global"},
|
||||||
|
scopeSlots: []int{0},
|
||||||
|
currentDepth: 0,
|
||||||
structs: make(map[string]*StructStatement),
|
structs: make(map[string]*StructStatement),
|
||||||
structIDs: make(map[uint16]*StructStatement),
|
structIDs: make(map[uint16]*StructStatement),
|
||||||
nextID: 1, // 0 reserved for non-struct types
|
nextID: 1, // 0 reserved for non-struct types
|
||||||
@ -113,20 +125,24 @@ func (p *Parser) isStructDefined(name string) bool {
|
|||||||
return exists
|
return exists
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scope management
|
// Scope management with slot allocation
|
||||||
func (p *Parser) enterScope(scopeType string) {
|
func (p *Parser) enterScope(scopeType string) {
|
||||||
p.scopes = append(p.scopes, make(map[string]bool))
|
p.scopes = append(p.scopes, make(map[string]*Variable))
|
||||||
p.scopeTypes = append(p.scopeTypes, scopeType)
|
p.scopeTypes = append(p.scopeTypes, scopeType)
|
||||||
|
p.scopeSlots = append(p.scopeSlots, 0)
|
||||||
|
p.currentDepth++
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) exitScope() {
|
func (p *Parser) exitScope() {
|
||||||
if len(p.scopes) > 1 {
|
if len(p.scopes) > 1 {
|
||||||
p.scopes = p.scopes[:len(p.scopes)-1]
|
p.scopes = p.scopes[:len(p.scopes)-1]
|
||||||
p.scopeTypes = p.scopeTypes[:len(p.scopeTypes)-1]
|
p.scopeTypes = p.scopeTypes[:len(p.scopeTypes)-1]
|
||||||
|
p.scopeSlots = p.scopeSlots[:len(p.scopeSlots)-1]
|
||||||
|
p.currentDepth--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) currentVariableScope() map[string]bool {
|
func (p *Parser) currentVariableScope() map[string]*Variable {
|
||||||
if len(p.scopeTypes) > 1 && p.scopeTypes[len(p.scopeTypes)-1] == "loop" {
|
if len(p.scopeTypes) > 1 && p.scopeTypes[len(p.scopeTypes)-1] == "loop" {
|
||||||
return p.scopes[len(p.scopes)-2]
|
return p.scopes[len(p.scopes)-2]
|
||||||
}
|
}
|
||||||
@ -135,19 +151,55 @@ func (p *Parser) currentVariableScope() map[string]bool {
|
|||||||
|
|
||||||
func (p *Parser) isVariableDeclared(name string) bool {
|
func (p *Parser) isVariableDeclared(name string) bool {
|
||||||
for i := len(p.scopes) - 1; i >= 0; i-- {
|
for i := len(p.scopes) - 1; i >= 0; i-- {
|
||||||
if p.scopes[i][name] {
|
if _, exists := p.scopes[i][name]; exists {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) declareVariable(name string) {
|
func (p *Parser) declareVariable(name string, typeHint TypeInfo) *Variable {
|
||||||
p.currentVariableScope()[name] = true
|
scope := p.currentVariableScope()
|
||||||
|
scopeIdx := len(p.scopes) - 1
|
||||||
|
if len(p.scopeTypes) > 1 && p.scopeTypes[len(p.scopeTypes)-1] == "loop" {
|
||||||
|
scopeIdx--
|
||||||
|
}
|
||||||
|
|
||||||
|
variable := &Variable{
|
||||||
|
Name: name,
|
||||||
|
ScopeDepth: p.currentDepth,
|
||||||
|
SlotIndex: p.scopeSlots[scopeIdx],
|
||||||
|
TypeHint: typeHint,
|
||||||
|
}
|
||||||
|
|
||||||
|
scope[name] = variable
|
||||||
|
p.scopeSlots[scopeIdx]++
|
||||||
|
return variable
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) declareLoopVariable(name string) {
|
func (p *Parser) declareLoopVariable(name string, typeHint TypeInfo) *Variable {
|
||||||
p.scopes[len(p.scopes)-1][name] = true
|
scope := p.scopes[len(p.scopes)-1]
|
||||||
|
scopeIdx := len(p.scopes) - 1
|
||||||
|
|
||||||
|
variable := &Variable{
|
||||||
|
Name: name,
|
||||||
|
ScopeDepth: p.currentDepth,
|
||||||
|
SlotIndex: p.scopeSlots[scopeIdx],
|
||||||
|
TypeHint: typeHint,
|
||||||
|
}
|
||||||
|
|
||||||
|
scope[name] = variable
|
||||||
|
p.scopeSlots[scopeIdx]++
|
||||||
|
return variable
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parser) lookupVariable(name string) *Variable {
|
||||||
|
for i := len(p.scopes) - 1; i >= 0; i-- {
|
||||||
|
if variable, exists := p.scopes[i][name]; exists {
|
||||||
|
return variable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseTypeHint parses optional type hint after colon, returns by value
|
// parseTypeHint parses optional type hint after colon, returns by value
|
||||||
@ -381,7 +433,7 @@ func (p *Parser) parseFunctionStatement() Statement {
|
|||||||
|
|
||||||
p.enterScope("function")
|
p.enterScope("function")
|
||||||
for _, param := range funcLit.Parameters {
|
for _, param := range funcLit.Parameters {
|
||||||
p.declareVariable(param.Name)
|
p.declareVariable(param.Name, param.TypeHint)
|
||||||
}
|
}
|
||||||
funcLit.Body = p.parseBlockStatements(END)
|
funcLit.Body = p.parseBlockStatements(END)
|
||||||
p.exitScope()
|
p.exitScope()
|
||||||
@ -436,9 +488,17 @@ func (p *Parser) parseIdentifierStatement() Statement {
|
|||||||
// Validate assignment target and check if it's a declaration
|
// Validate assignment target and check if it's a declaration
|
||||||
switch target := expr.(type) {
|
switch target := expr.(type) {
|
||||||
case *Identifier:
|
case *Identifier:
|
||||||
assignment.IsDeclaration = !p.isVariableDeclared(target.Value)
|
if variable := p.lookupVariable(target.Value); variable != nil {
|
||||||
if assignment.IsDeclaration {
|
// Existing variable - resolve it
|
||||||
p.declareVariable(target.Value)
|
target.ScopeDepth = variable.ScopeDepth
|
||||||
|
target.SlotIndex = variable.SlotIndex
|
||||||
|
assignment.IsDeclaration = false
|
||||||
|
} else {
|
||||||
|
// New variable declaration - create and resolve
|
||||||
|
variable := p.declareVariable(target.Value, typeHint)
|
||||||
|
target.ScopeDepth = variable.ScopeDepth
|
||||||
|
target.SlotIndex = variable.SlotIndex
|
||||||
|
assignment.IsDeclaration = true
|
||||||
}
|
}
|
||||||
case *DotExpression, *IndexExpression:
|
case *DotExpression, *IndexExpression:
|
||||||
assignment.IsDeclaration = false
|
assignment.IsDeclaration = false
|
||||||
@ -626,7 +686,12 @@ func (p *Parser) parseNumericForStatement(variable *Identifier, pos Position) *F
|
|||||||
p.nextToken()
|
p.nextToken()
|
||||||
|
|
||||||
p.enterScope("loop")
|
p.enterScope("loop")
|
||||||
p.declareLoopVariable(variable.Value)
|
// Declare and resolve loop variable
|
||||||
|
loopVar := p.declareLoopVariable(variable.Value, NumberType)
|
||||||
|
variable.ScopeDepth = loopVar.ScopeDepth
|
||||||
|
variable.SlotIndex = loopVar.SlotIndex
|
||||||
|
variable.typeInfo = NumberType
|
||||||
|
|
||||||
stmt.Body = p.parseBlockStatements(END)
|
stmt.Body = p.parseBlockStatements(END)
|
||||||
p.exitScope()
|
p.exitScope()
|
||||||
|
|
||||||
@ -677,10 +742,20 @@ func (p *Parser) parseForInStatement(firstVar *Identifier, pos Position) *ForInS
|
|||||||
p.nextToken()
|
p.nextToken()
|
||||||
|
|
||||||
p.enterScope("loop")
|
p.enterScope("loop")
|
||||||
|
|
||||||
|
// Declare and resolve loop variables
|
||||||
if stmt.Key != nil {
|
if stmt.Key != nil {
|
||||||
p.declareLoopVariable(stmt.Key.Value)
|
keyVar := p.declareLoopVariable(stmt.Key.Value, AnyType)
|
||||||
|
stmt.Key.ScopeDepth = keyVar.ScopeDepth
|
||||||
|
stmt.Key.SlotIndex = keyVar.SlotIndex
|
||||||
|
stmt.Key.typeInfo = AnyType
|
||||||
}
|
}
|
||||||
p.declareLoopVariable(stmt.Value.Value)
|
|
||||||
|
valueVar := p.declareLoopVariable(stmt.Value.Value, AnyType)
|
||||||
|
stmt.Value.ScopeDepth = valueVar.ScopeDepth
|
||||||
|
stmt.Value.SlotIndex = valueVar.SlotIndex
|
||||||
|
stmt.Value.typeInfo = AnyType
|
||||||
|
|
||||||
stmt.Body = p.parseBlockStatements(END)
|
stmt.Body = p.parseBlockStatements(END)
|
||||||
p.exitScope()
|
p.exitScope()
|
||||||
|
|
||||||
@ -806,7 +881,21 @@ func (p *Parser) ParseExpression(precedence Precedence) Expression {
|
|||||||
|
|
||||||
// Expression parsing functions
|
// Expression parsing functions
|
||||||
func (p *Parser) parseIdentifier() Expression {
|
func (p *Parser) parseIdentifier() Expression {
|
||||||
return &Identifier{Value: p.curToken.Literal, Position: p.pos()}
|
ident := &Identifier{
|
||||||
|
Value: p.curToken.Literal,
|
||||||
|
ScopeDepth: -1,
|
||||||
|
SlotIndex: -1,
|
||||||
|
Position: p.pos(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve variable if it exists
|
||||||
|
if variable := p.lookupVariable(ident.Value); variable != nil {
|
||||||
|
ident.ScopeDepth = variable.ScopeDepth
|
||||||
|
ident.SlotIndex = variable.SlotIndex
|
||||||
|
ident.typeInfo = variable.TypeHint
|
||||||
|
}
|
||||||
|
|
||||||
|
return ident
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) parseNumberLiteral() Expression {
|
func (p *Parser) parseNumberLiteral() Expression {
|
||||||
@ -947,9 +1036,17 @@ func (p *Parser) parseParenthesizedAssignment() Expression {
|
|||||||
|
|
||||||
// Handle variable declaration for assignment expressions
|
// Handle variable declaration for assignment expressions
|
||||||
if ident, ok := target.(*Identifier); ok {
|
if ident, ok := target.(*Identifier); ok {
|
||||||
assignExpr.IsDeclaration = !p.isVariableDeclared(ident.Value)
|
if variable := p.lookupVariable(ident.Value); variable != nil {
|
||||||
if assignExpr.IsDeclaration {
|
// Existing variable
|
||||||
p.declareVariable(ident.Value)
|
ident.ScopeDepth = variable.ScopeDepth
|
||||||
|
ident.SlotIndex = variable.SlotIndex
|
||||||
|
assignExpr.IsDeclaration = false
|
||||||
|
} else {
|
||||||
|
// New variable declaration
|
||||||
|
newVar := p.declareVariable(ident.Value, UnknownType)
|
||||||
|
ident.ScopeDepth = newVar.ScopeDepth
|
||||||
|
ident.SlotIndex = newVar.SlotIndex
|
||||||
|
assignExpr.IsDeclaration = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -977,10 +1074,21 @@ func (p *Parser) parseFunctionLiteral() Expression {
|
|||||||
p.nextToken()
|
p.nextToken()
|
||||||
|
|
||||||
p.enterScope("function")
|
p.enterScope("function")
|
||||||
|
|
||||||
|
// Declare function parameters as resolved variables
|
||||||
for _, param := range fn.Parameters {
|
for _, param := range fn.Parameters {
|
||||||
p.declareVariable(param.Name)
|
p.declareVariable(param.Name, param.TypeHint)
|
||||||
|
param.Position = Position{Line: p.curToken.Line, Column: p.curToken.Column}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn.Body = p.parseBlockStatements(END)
|
fn.Body = p.parseBlockStatements(END)
|
||||||
|
|
||||||
|
// Calculate function metadata before exiting scope
|
||||||
|
scopeIdx := len(p.scopes) - 1
|
||||||
|
fn.LocalCount = p.scopeSlots[scopeIdx]
|
||||||
|
fn.UpvalueCount = 0 // TODO: Calculate captured variables
|
||||||
|
fn.MaxStackDepth = 0 // TODO: Calculate max expression depth
|
||||||
|
|
||||||
p.exitScope()
|
p.exitScope()
|
||||||
|
|
||||||
if !p.curTokenIs(END) {
|
if !p.curTokenIs(END) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user