move types to types

This commit is contained in:
Sky Johnson 2025-05-06 12:09:17 -05:00
parent e536acb4c8
commit 6e5c35c9ee
4 changed files with 66 additions and 66 deletions

View File

@ -2,14 +2,14 @@ package compiler
import (
"git.sharkk.net/Sharkk/Mako/parser"
"git.sharkk.net/Sharkk/Mako/vm"
"git.sharkk.net/Sharkk/Mako/types"
)
// Compile converts AST to bytecode
func Compile(program *parser.Program) *vm.Bytecode {
func Compile(program *parser.Program) *types.Bytecode {
c := &compiler{
constants: []any{},
instructions: []vm.Instruction{},
instructions: []types.Instruction{},
scopes: []scope{},
}
@ -22,7 +22,7 @@ func Compile(program *parser.Program) *vm.Bytecode {
c.exitScope()
return &vm.Bytecode{
return &types.Bytecode{
Constants: c.constants,
Instructions: c.instructions,
}
@ -34,7 +34,7 @@ type scope struct {
type compiler struct {
constants []any
instructions []vm.Instruction
instructions []types.Instruction
scopes []scope
}
@ -42,12 +42,12 @@ func (c *compiler) enterScope() {
c.scopes = append(c.scopes, scope{
variables: make(map[string]bool),
})
c.emit(vm.OpEnterScope, 0)
c.emit(types.OpEnterScope, 0)
}
func (c *compiler) exitScope() {
c.scopes = c.scopes[:len(c.scopes)-1]
c.emit(vm.OpExitScope, 0)
c.emit(types.OpExitScope, 0)
}
func (c *compiler) declareVariable(name string) {
@ -73,21 +73,21 @@ func (c *compiler) compileStatement(stmt parser.Statement) {
// Use SetGlobal for top-level variables to persist between REPL lines
if len(c.scopes) <= 1 {
c.emit(vm.OpSetGlobal, nameIndex)
c.emit(types.OpSetGlobal, nameIndex)
} else {
c.declareVariable(s.Name.Value)
c.emit(vm.OpSetLocal, nameIndex)
c.emit(types.OpSetLocal, nameIndex)
}
case *parser.IndexAssignmentStatement:
c.compileExpression(s.Left)
c.compileExpression(s.Index)
c.compileExpression(s.Value)
c.emit(vm.OpSetIndex, 0)
c.emit(types.OpSetIndex, 0)
case *parser.EchoStatement:
c.compileExpression(s.Value)
c.emit(vm.OpEcho, 0)
c.emit(types.OpEcho, 0)
case *parser.BlockStatement:
c.enterScope()
@ -102,48 +102,48 @@ func (c *compiler) compileExpression(expr parser.Expression) {
switch e := expr.(type) {
case *parser.StringLiteral:
constIndex := c.addConstant(e.Value)
c.emit(vm.OpConstant, constIndex)
c.emit(types.OpConstant, constIndex)
case *parser.NumberLiteral:
constIndex := c.addConstant(e.Value)
c.emit(vm.OpConstant, constIndex)
c.emit(types.OpConstant, constIndex)
case *parser.Identifier:
nameIndex := c.addConstant(e.Value)
// Check if it's a local variable first
if c.isLocalVariable(e.Value) {
c.emit(vm.OpGetLocal, nameIndex)
c.emit(types.OpGetLocal, nameIndex)
} else {
// Otherwise treat as global
c.emit(vm.OpGetGlobal, nameIndex)
c.emit(types.OpGetGlobal, nameIndex)
}
case *parser.TableLiteral:
c.emit(vm.OpNewTable, 0)
c.emit(types.OpNewTable, 0)
for key, value := range e.Pairs {
c.emit(vm.OpDup, 0)
c.emit(types.OpDup, 0)
// Special handling for identifier keys in tables
if ident, ok := key.(*parser.Identifier); ok {
// Treat identifiers as string literals in table keys
strIndex := c.addConstant(ident.Value)
c.emit(vm.OpConstant, strIndex)
c.emit(types.OpConstant, strIndex)
} else {
// For other expressions, compile normally
c.compileExpression(key)
}
c.compileExpression(value)
c.emit(vm.OpSetIndex, 0)
c.emit(vm.OpPop, 0)
c.emit(types.OpSetIndex, 0)
c.emit(types.OpPop, 0)
}
case *parser.IndexExpression:
c.compileExpression(e.Left)
c.compileExpression(e.Index)
c.emit(vm.OpGetIndex, 0)
c.emit(types.OpGetIndex, 0)
}
}
@ -152,8 +152,8 @@ func (c *compiler) addConstant(value any) int {
return len(c.constants) - 1
}
func (c *compiler) emit(op vm.Opcode, operand int) {
instruction := vm.Instruction{
func (c *compiler) emit(op types.Opcode, operand int) {
instruction := types.Instruction{
Opcode: op,
Operand: operand,
}

View File

View File

@ -7,9 +7,37 @@ const (
TypeNumber
TypeString
TypeBoolean
TypeTable // New type for tables
TypeTable
)
type Opcode byte
const (
OpConstant Opcode = iota
OpSetLocal
OpGetLocal
OpSetGlobal
OpGetGlobal
OpEcho
OpNewTable
OpSetIndex
OpGetIndex
OpDup
OpPop
OpEnterScope
OpExitScope
)
type Instruction struct {
Opcode Opcode
Operand int
}
type Bytecode struct {
Constants []any
Instructions []Instruction
}
type Value struct {
Type ValueType
Data any

View File

@ -6,34 +6,6 @@ import (
"git.sharkk.net/Sharkk/Mako/types"
)
type Opcode byte
const (
OpConstant Opcode = iota
OpSetLocal // Set local variable
OpGetLocal // Get local variable
OpSetGlobal // Set global variable
OpGetGlobal // Get global variable
OpEcho
OpNewTable
OpSetIndex
OpGetIndex
OpDup
OpPop
OpEnterScope // New opcode for entering a block
OpExitScope // New opcode for exiting a block
)
type Instruction struct {
Opcode Opcode
Operand int
}
type Bytecode struct {
Constants []any
Instructions []Instruction
}
// Scope represents a lexical scope
type Scope struct {
Variables map[string]types.Value
@ -56,14 +28,14 @@ func New() *VM {
}
}
func (vm *VM) Run(bytecode *Bytecode) {
func (vm *VM) Run(bytecode *types.Bytecode) {
vm.constants = bytecode.Constants
for ip := 0; ip < len(bytecode.Instructions); ip++ {
instruction := bytecode.Instructions[ip]
switch instruction.Opcode {
case OpConstant:
case types.OpConstant:
constIndex := instruction.Operand
constant := vm.constants[constIndex]
@ -74,7 +46,7 @@ func (vm *VM) Run(bytecode *Bytecode) {
vm.push(types.NewNumber(v))
}
case OpSetLocal:
case types.OpSetLocal:
constIndex := instruction.Operand
name := vm.constants[constIndex].(string)
value := vm.pop()
@ -87,7 +59,7 @@ func (vm *VM) Run(bytecode *Bytecode) {
vm.globals[name] = value
}
case OpGetLocal:
case types.OpGetLocal:
constIndex := instruction.Operand
name := vm.constants[constIndex].(string)
@ -110,13 +82,13 @@ func (vm *VM) Run(bytecode *Bytecode) {
}
}
case OpSetGlobal:
case types.OpSetGlobal:
constIndex := instruction.Operand
name := vm.constants[constIndex].(string)
value := vm.pop()
vm.globals[name] = value
case OpGetGlobal:
case types.OpGetGlobal:
constIndex := instruction.Operand
name := vm.constants[constIndex].(string)
if val, ok := vm.globals[name]; ok {
@ -125,22 +97,22 @@ func (vm *VM) Run(bytecode *Bytecode) {
vm.push(types.NewNull())
}
case OpEnterScope:
case types.OpEnterScope:
// Push a new scope
vm.scopes = append(vm.scopes, Scope{
Variables: make(map[string]types.Value),
})
case OpExitScope:
case types.OpExitScope:
// Pop the current scope
if len(vm.scopes) > 0 {
vm.scopes = vm.scopes[:len(vm.scopes)-1]
}
case OpNewTable:
case types.OpNewTable:
vm.push(types.NewTableValue())
case OpSetIndex:
case types.OpSetIndex:
value := vm.pop()
key := vm.pop()
tableVal := vm.pop()
@ -155,7 +127,7 @@ func (vm *VM) Run(bytecode *Bytecode) {
table.Set(key, value)
vm.push(tableVal)
case OpGetIndex:
case types.OpGetIndex:
key := vm.pop()
tableVal := vm.pop()
@ -169,15 +141,15 @@ func (vm *VM) Run(bytecode *Bytecode) {
value := table.Get(key)
vm.push(value)
case OpDup:
case types.OpDup:
if vm.sp > 0 {
vm.push(vm.stack[vm.sp-1])
}
case OpPop:
case types.OpPop:
vm.pop()
case OpEcho:
case types.OpEcho:
value := vm.pop()
switch value.Type {
case types.TypeString: