functions now capture variables :D

This commit is contained in:
Neemek 2026-07-09 23:21:41 +02:00
parent 43e450c207
commit d315a53fbd
Signed by: neemek
GPG key ID: 84FFE4D7D40AB25E
5 changed files with 49 additions and 11 deletions

View file

@ -587,6 +587,7 @@ func (c *Compiler) compile(tree Node) error {
n.yield,
c.Chunk,
nil,
nil,
}
// restore old chunk and ip
@ -958,6 +959,13 @@ func (c *Compiler) deduceSignature(tree Node) (TypeSignature, error) {
}
return nil, c.error(fmt.Sprintf("unimplemented result type deduction for unary %s", n.UnaryOperation), n)
case BlockNodeType:
n := tree.(*BlockNode)
if len(n.statements) == 0 {
return &NilSignature{}, nil
}
return c.deduceSignature(n.statements[len(n.statements)-1])
default:
return nil, c.error(fmt.Sprintf("impossible to deduce signature of %s", tree.Type()), tree)
}

View file

@ -1387,9 +1387,15 @@ func (p *Parser) parseSignature() (TypeSignature, error) {
in = append(in, sig)
}
out, err := p.parseSignature()
if err != nil {
return nil, err
var out TypeSignature
var err error
if p.accept(TokenArrow) {
out, err = p.parseSignature()
if err != nil {
return nil, err
}
} else {
out = &NilSignature{}
}
s = &FunctionSignature{

View file

@ -603,6 +603,7 @@ type FunctionValue struct {
Yield TypeSignature
Chunk *Chunk
Parent Value
Scope *Scope
}
func (v *FunctionValue) Type() ValueType {
@ -633,6 +634,7 @@ func (v *FunctionValue) Clone() Value {
v.Yield,
v.Chunk,
v.Parent,
v.Scope,
}
}

View file

@ -698,7 +698,13 @@ func (vm *VM) Next() bool {
vm.stack.Pop()
case InstructionConstant:
vm.stack.Push(vm.ReadConstant())
c := vm.ReadConstant()
if c, ok := c.(*FunctionValue); ok {
c.Scope = vm.scope
}
vm.stack.Push(c)
case InstructionAddFloat:
r := vm.stack.Pop().(*FloatValue).Number
@ -840,6 +846,7 @@ func (vm *VM) Next() bool {
scope: vm.scope,
})
vm.scope = f.Scope
vm.descend()
for i := len(f.Params) - 1; i >= 0; i-- {
@ -993,6 +1000,15 @@ func (vm *VM) Next() bool {
vm.stack.Push(member)
case InstructionBreakpoint:
/*
// I'm keeping this
s := vm.scope
log.Printf("breakpoint %d", vm.ip)
for s != nil {
log.Printf("%s", s.current)
s = s.parent
}
*/
vm.stack.Push(&NilValue{})
default:
@ -1122,7 +1138,7 @@ func (vm *VM) HasNext() bool {
}
func (vm *VM) GetConstant(id Bytecode) Value {
return vm.chunk.Constants[id]
return vm.chunk.Constants[id].Clone()
}
func (vm *VM) ReadConstant() Value {

View file

@ -1,10 +1,16 @@
fn counter() -> (fn() -> int) {
i := 0
fn double(a: int) -> int {
2*a
fn() -> int {
i = i + 1
}
}
a := 1
next := counter()
other := counter()
a = 2
println(double(2) == 4)
println(next())
println(next())
println(other())
println(other())
println(next())