functions now capture variables :D
This commit is contained in:
parent
43e450c207
commit
d315a53fbd
5 changed files with 49 additions and 11 deletions
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
20
core/vm.go
20
core/vm.go
|
|
@ -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 {
|
||||
|
|
|
|||
18
era3.ang
18
era3.ang
|
|
@ -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())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue