compiler 2
This commit is contained in:
parent
07edd82c8b
commit
aee29ac884
@ -391,6 +391,313 @@ func (c *Compiler) compileWhileStatement(node *parser.WhileStatement) {
|
|||||||
c.current.ExitLoop()
|
c.current.ExitLoop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For loop compilation
|
||||||
|
func (c *Compiler) compileForStatement(node *parser.ForStatement) {
|
||||||
|
c.current.BeginScope()
|
||||||
|
c.current.EnterLoop()
|
||||||
|
|
||||||
|
// Initialize loop variable
|
||||||
|
c.compileExpression(node.Start)
|
||||||
|
if err := c.current.AddLocal(node.Variable.Value); err != nil {
|
||||||
|
c.addError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.current.MarkInitialized()
|
||||||
|
loopVar := len(c.current.Locals) - 1
|
||||||
|
|
||||||
|
// Compile end value
|
||||||
|
c.compileExpression(node.End)
|
||||||
|
endSlot := len(c.current.Locals)
|
||||||
|
if err := c.current.AddLocal("__end"); err != nil {
|
||||||
|
c.addError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.current.MarkInitialized()
|
||||||
|
|
||||||
|
// Compile step value (default 1)
|
||||||
|
if node.Step != nil {
|
||||||
|
c.compileExpression(node.Step)
|
||||||
|
} else {
|
||||||
|
value := Value{Type: ValueNumber, Data: float64(1)}
|
||||||
|
index := c.current.AddConstant(value)
|
||||||
|
if index == -1 {
|
||||||
|
c.addError("too many constants")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.current.EmitInstruction(OpLoadConst, uint16(index))
|
||||||
|
}
|
||||||
|
stepSlot := len(c.current.Locals)
|
||||||
|
if err := c.current.AddLocal("__step"); err != nil {
|
||||||
|
c.addError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.current.MarkInitialized()
|
||||||
|
|
||||||
|
// Loop condition: check if loop variable <= end (for positive step)
|
||||||
|
conditionStart := len(c.current.Chunk.Code)
|
||||||
|
c.current.EmitInstruction(OpLoadLocal, uint16(loopVar)) // Load loop var
|
||||||
|
c.current.EmitInstruction(OpLoadLocal, uint16(endSlot)) // Load end
|
||||||
|
c.current.EmitInstruction(OpLte) // Compare
|
||||||
|
exitJump := c.current.EmitJump(OpJumpIfFalse)
|
||||||
|
c.current.EmitInstruction(OpPop)
|
||||||
|
|
||||||
|
// Loop body
|
||||||
|
for _, stmt := range node.Body {
|
||||||
|
c.compileStatement(stmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment loop variable: var = var + step
|
||||||
|
c.current.EmitInstruction(OpLoadLocal, uint16(loopVar)) // Load current value
|
||||||
|
c.current.EmitInstruction(OpLoadLocal, uint16(stepSlot)) // Load step
|
||||||
|
c.current.EmitInstruction(OpAdd) // Add
|
||||||
|
c.current.EmitInstruction(OpStoreLocal, uint16(loopVar)) // Store back
|
||||||
|
|
||||||
|
// Jump back to condition
|
||||||
|
jumpBack := len(c.current.Chunk.Code) - conditionStart + 2
|
||||||
|
c.current.EmitInstruction(OpJump, uint16(jumpBack))
|
||||||
|
|
||||||
|
// Exit
|
||||||
|
c.current.PatchJump(exitJump)
|
||||||
|
c.current.EmitInstruction(OpPop)
|
||||||
|
|
||||||
|
c.current.ExitLoop()
|
||||||
|
c.current.EndScope()
|
||||||
|
}
|
||||||
|
|
||||||
|
// For-in loop compilation
|
||||||
|
func (c *Compiler) compileForInStatement(node *parser.ForInStatement) {
|
||||||
|
c.current.BeginScope()
|
||||||
|
c.current.EnterLoop()
|
||||||
|
|
||||||
|
// Compile iterable and set up iterator
|
||||||
|
c.compileExpression(node.Iterable)
|
||||||
|
|
||||||
|
// For simplicity, assume table iteration
|
||||||
|
// In a full implementation, we'd need to handle different iterator types
|
||||||
|
|
||||||
|
// Create iterator variables
|
||||||
|
if node.Key != nil {
|
||||||
|
if err := c.current.AddLocal(node.Key.Value); err != nil {
|
||||||
|
c.addError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.current.MarkInitialized()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.current.AddLocal(node.Value.Value); err != nil {
|
||||||
|
c.addError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.current.MarkInitialized()
|
||||||
|
|
||||||
|
// Loop condition (simplified - would need actual iterator logic)
|
||||||
|
conditionStart := len(c.current.Chunk.Code)
|
||||||
|
|
||||||
|
// For now, just emit a simple condition that will be false
|
||||||
|
// In real implementation, this would call iterator methods
|
||||||
|
nilValue := Value{Type: ValueNil, Data: nil}
|
||||||
|
index := c.current.AddConstant(nilValue)
|
||||||
|
if index == -1 {
|
||||||
|
c.addError("too many constants")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.current.EmitInstruction(OpLoadConst, uint16(index))
|
||||||
|
c.current.EmitInstruction(OpNot) // Convert nil to true, everything else to false
|
||||||
|
|
||||||
|
exitJump := c.current.EmitJump(OpJumpIfFalse)
|
||||||
|
c.current.EmitInstruction(OpPop)
|
||||||
|
|
||||||
|
// Loop body
|
||||||
|
for _, stmt := range node.Body {
|
||||||
|
c.compileStatement(stmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jump back to condition
|
||||||
|
jumpBack := len(c.current.Chunk.Code) - conditionStart + 2
|
||||||
|
c.current.EmitInstruction(OpJump, uint16(jumpBack))
|
||||||
|
|
||||||
|
// Exit
|
||||||
|
c.current.PatchJump(exitJump)
|
||||||
|
c.current.EmitInstruction(OpPop)
|
||||||
|
|
||||||
|
c.current.ExitLoop()
|
||||||
|
c.current.EndScope()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function compilation
|
||||||
|
func (c *Compiler) compileFunctionLiteral(node *parser.FunctionLiteral) {
|
||||||
|
// Create new compiler state for function
|
||||||
|
enclosing := c.current
|
||||||
|
c.current = NewCompilerState(FunctionTypeFunction)
|
||||||
|
c.current.parent = enclosing
|
||||||
|
c.enclosing = enclosing
|
||||||
|
|
||||||
|
// Begin function scope
|
||||||
|
c.current.BeginScope()
|
||||||
|
|
||||||
|
// Add parameters as local variables
|
||||||
|
for _, param := range node.Parameters {
|
||||||
|
if err := c.current.AddLocal(param.Name); err != nil {
|
||||||
|
c.addError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.current.MarkInitialized()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile function body
|
||||||
|
for _, stmt := range node.Body {
|
||||||
|
c.compileStatement(stmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implicit return nil if no explicit return
|
||||||
|
c.current.EmitInstruction(OpReturnNil)
|
||||||
|
|
||||||
|
// Create function object
|
||||||
|
function := Function{
|
||||||
|
Name: "", // Anonymous function
|
||||||
|
Arity: len(node.Parameters),
|
||||||
|
Variadic: node.Variadic,
|
||||||
|
LocalCount: len(c.current.Locals),
|
||||||
|
UpvalCount: len(c.current.Upvalues),
|
||||||
|
Chunk: *c.current.Chunk,
|
||||||
|
Defaults: []Value{}, // TODO: Handle default parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add function to parent chunk
|
||||||
|
functionIndex := len(enclosing.Chunk.Functions)
|
||||||
|
enclosing.Chunk.Functions = append(enclosing.Chunk.Functions, function)
|
||||||
|
|
||||||
|
// Restore enclosing state
|
||||||
|
c.current = enclosing
|
||||||
|
c.enclosing = nil
|
||||||
|
|
||||||
|
// Emit closure instruction
|
||||||
|
c.current.EmitInstruction(OpClosure, uint16(functionIndex), uint16(function.UpvalCount))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Struct compilation
|
||||||
|
func (c *Compiler) compileStructStatement(node *parser.StructStatement) {
|
||||||
|
// Convert parser fields to compiler fields
|
||||||
|
fields := make([]StructField, len(node.Fields))
|
||||||
|
for i, field := range node.Fields {
|
||||||
|
fields[i] = StructField{
|
||||||
|
Name: field.Name,
|
||||||
|
Type: c.typeInfoToValueType(field.TypeHint),
|
||||||
|
Offset: uint16(i),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create struct definition
|
||||||
|
structDef := Struct{
|
||||||
|
Name: node.Name,
|
||||||
|
Fields: fields,
|
||||||
|
Methods: make(map[string]uint16),
|
||||||
|
ID: node.ID,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to chunk
|
||||||
|
c.current.Chunk.Structs = append(c.current.Chunk.Structs, structDef)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Compiler) compileMethodDefinition(node *parser.MethodDefinition) {
|
||||||
|
// Compile method as a function
|
||||||
|
enclosing := c.current
|
||||||
|
c.current = NewCompilerState(FunctionTypeMethod)
|
||||||
|
c.current.parent = enclosing
|
||||||
|
c.enclosing = enclosing
|
||||||
|
|
||||||
|
// Begin function scope
|
||||||
|
c.current.BeginScope()
|
||||||
|
|
||||||
|
// Add 'self' parameter
|
||||||
|
if err := c.current.AddLocal("self"); err != nil {
|
||||||
|
c.addError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.current.MarkInitialized()
|
||||||
|
|
||||||
|
// Add method parameters
|
||||||
|
for _, param := range node.Function.Parameters {
|
||||||
|
if err := c.current.AddLocal(param.Name); err != nil {
|
||||||
|
c.addError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.current.MarkInitialized()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile method body
|
||||||
|
for _, stmt := range node.Function.Body {
|
||||||
|
c.compileStatement(stmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implicit return nil
|
||||||
|
c.current.EmitInstruction(OpReturnNil)
|
||||||
|
|
||||||
|
// Create function object
|
||||||
|
function := Function{
|
||||||
|
Name: node.MethodName,
|
||||||
|
Arity: len(node.Function.Parameters) + 1, // +1 for self
|
||||||
|
Variadic: node.Function.Variadic,
|
||||||
|
LocalCount: len(c.current.Locals),
|
||||||
|
UpvalCount: len(c.current.Upvalues),
|
||||||
|
Chunk: *c.current.Chunk,
|
||||||
|
Defaults: []Value{},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to parent chunk
|
||||||
|
functionIndex := len(enclosing.Chunk.Functions)
|
||||||
|
enclosing.Chunk.Functions = append(enclosing.Chunk.Functions, function)
|
||||||
|
|
||||||
|
// Find struct and add method reference
|
||||||
|
for i := range enclosing.Chunk.Structs {
|
||||||
|
if enclosing.Chunk.Structs[i].ID == node.StructID {
|
||||||
|
enclosing.Chunk.Structs[i].Methods[node.MethodName] = uint16(functionIndex)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore state
|
||||||
|
c.current = enclosing
|
||||||
|
c.enclosing = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Compiler) compileStructConstructor(node *parser.StructConstructor) {
|
||||||
|
// Create new struct instance
|
||||||
|
c.current.EmitInstruction(OpNewStruct, node.StructID)
|
||||||
|
|
||||||
|
// Initialize fields
|
||||||
|
for _, field := range node.Fields {
|
||||||
|
if field.Key != nil {
|
||||||
|
// Named field assignment
|
||||||
|
c.current.EmitInstruction(OpDup) // Duplicate struct reference
|
||||||
|
|
||||||
|
// Get field name
|
||||||
|
var fieldName string
|
||||||
|
if ident, ok := field.Key.(*parser.Identifier); ok {
|
||||||
|
fieldName = ident.Value
|
||||||
|
} else if str, ok := field.Key.(*parser.StringLiteral); ok {
|
||||||
|
fieldName = str.Value
|
||||||
|
} else {
|
||||||
|
c.addError("struct field names must be identifiers or strings")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find field index in struct definition
|
||||||
|
fieldIndex := c.findStructFieldIndex(node.StructID, fieldName)
|
||||||
|
if fieldIndex == -1 {
|
||||||
|
c.addError(fmt.Sprintf("struct has no field '%s'", fieldName))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
c.compileExpression(field.Value)
|
||||||
|
c.current.EmitInstruction(OpSetProperty, uint16(fieldIndex))
|
||||||
|
} else {
|
||||||
|
// Positional field assignment (not typical for structs)
|
||||||
|
c.addError("struct constructors require named field assignments")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Table operations
|
// Table operations
|
||||||
func (c *Compiler) compileTableLiteral(node *parser.TableLiteral) {
|
func (c *Compiler) compileTableLiteral(node *parser.TableLiteral) {
|
||||||
c.current.EmitInstruction(OpNewTable)
|
c.current.EmitInstruction(OpNewTable)
|
||||||
@ -427,7 +734,7 @@ func (c *Compiler) compileIndexExpression(node *parser.IndexExpression) {
|
|||||||
c.current.EmitInstruction(OpGetIndex)
|
c.current.EmitInstruction(OpGetIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function compilation
|
// Function calls
|
||||||
func (c *Compiler) compileCallExpression(node *parser.CallExpression) {
|
func (c *Compiler) compileCallExpression(node *parser.CallExpression) {
|
||||||
c.compileExpression(node.Function)
|
c.compileExpression(node.Function)
|
||||||
|
|
||||||
@ -464,37 +771,6 @@ func (c *Compiler) compileExitStatement(node *parser.ExitStatement) {
|
|||||||
c.current.EmitInstruction(OpExit)
|
c.current.EmitInstruction(OpExit)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Placeholder implementations for complex features
|
|
||||||
func (c *Compiler) compileStructStatement(node *parser.StructStatement) {
|
|
||||||
// TODO: Implement struct compilation
|
|
||||||
c.addError("struct compilation not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Compiler) compileMethodDefinition(node *parser.MethodDefinition) {
|
|
||||||
// TODO: Implement method compilation
|
|
||||||
c.addError("method compilation not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Compiler) compileStructConstructor(node *parser.StructConstructor) {
|
|
||||||
// TODO: Implement struct constructor compilation
|
|
||||||
c.addError("struct constructor compilation not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Compiler) compileFunctionLiteral(node *parser.FunctionLiteral) {
|
|
||||||
// TODO: Implement function literal compilation
|
|
||||||
c.addError("function literal compilation not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Compiler) compileForStatement(node *parser.ForStatement) {
|
|
||||||
// TODO: Implement numeric for loop compilation
|
|
||||||
c.addError("for statement compilation not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Compiler) compileForInStatement(node *parser.ForInStatement) {
|
|
||||||
// TODO: Implement for-in loop compilation
|
|
||||||
c.addError("for-in statement compilation not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper methods
|
// Helper methods
|
||||||
func (c *Compiler) resolveUpvalue(name string) int {
|
func (c *Compiler) resolveUpvalue(name string) int {
|
||||||
if c.enclosing == nil {
|
if c.enclosing == nil {
|
||||||
@ -525,6 +801,41 @@ func (c *Compiler) resolveUpvalueInEnclosing(name string) int {
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Compiler) typeInfoToValueType(typeInfo parser.TypeInfo) ValueType {
|
||||||
|
switch typeInfo.Type {
|
||||||
|
case parser.TypeNumber:
|
||||||
|
return ValueNumber
|
||||||
|
case parser.TypeString:
|
||||||
|
return ValueString
|
||||||
|
case parser.TypeBool:
|
||||||
|
return ValueBool
|
||||||
|
case parser.TypeNil:
|
||||||
|
return ValueNil
|
||||||
|
case parser.TypeTable:
|
||||||
|
return ValueTable
|
||||||
|
case parser.TypeFunction:
|
||||||
|
return ValueFunction
|
||||||
|
case parser.TypeStruct:
|
||||||
|
return ValueStruct
|
||||||
|
default:
|
||||||
|
return ValueNil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Compiler) findStructFieldIndex(structID uint16, fieldName string) int {
|
||||||
|
for _, structDef := range c.current.Chunk.Structs {
|
||||||
|
if structDef.ID == structID {
|
||||||
|
for i, field := range structDef.Fields {
|
||||||
|
if field.Name == fieldName {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Compiler) addError(message string) {
|
func (c *Compiler) addError(message string) {
|
||||||
c.errors = append(c.errors, CompileError{
|
c.errors = append(c.errors, CompileError{
|
||||||
Message: message,
|
Message: message,
|
||||||
|
@ -23,6 +23,7 @@ type CompilerState struct {
|
|||||||
ContinueJumps []int // Continue jump addresses for loops
|
ContinueJumps []int // Continue jump addresses for loops
|
||||||
LoopStart int // Start of current loop for continue
|
LoopStart int // Start of current loop for continue
|
||||||
LoopDepth int // Current loop nesting depth
|
LoopDepth int // Current loop nesting depth
|
||||||
|
parent *CompilerState // Parent compiler state for nested functions
|
||||||
}
|
}
|
||||||
|
|
||||||
// Local represents a local variable during compilation
|
// Local represents a local variable during compilation
|
||||||
@ -74,6 +75,7 @@ func NewCompilerState(functionType FunctionType) *CompilerState {
|
|||||||
ContinueJumps: make([]int, 0),
|
ContinueJumps: make([]int, 0),
|
||||||
LoopStart: -1,
|
LoopStart: -1,
|
||||||
LoopDepth: 0,
|
LoopDepth: 0,
|
||||||
|
parent: nil,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user