summaryrefslogtreecommitdiff
path: root/parser/compiler.go
diff options
context:
space:
mode:
authorMarc Vertes <mvertes@free.fr>2024-07-18 12:56:29 +0200
committerGitHub <noreply@github.com>2024-07-18 12:56:29 +0200
commitdabd9e5eb81bbc9aeaeb32fb3e3ce83eef258a77 (patch)
tree32be6a4cecf83487dd6a91e8a9aa1da709840b0f /parser/compiler.go
parent1a2b2cb565ebf701f43012e1fce5552398d622a9 (diff)
fix (parser): don't panic if assign of define untyped value (#10)
* fix (parser): don't panic if assign of define untyped value In case of defining or assigning to untyped value, the type has to be taken from the source value instead of the target value. The vm test coverage has also been slightly improved. * fix and simplify Token.Name() * improve parser errors
Diffstat (limited to 'parser/compiler.go')
-rw-r--r--parser/compiler.go25
1 files changed, 17 insertions, 8 deletions
diff --git a/parser/compiler.go b/parser/compiler.go
index 3b9a32d..05462eb 100644
--- a/parser/compiler.go
+++ b/parser/compiler.go
@@ -61,13 +61,14 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
case lang.String:
s := t.Block()
+ v := vm.Value{Data: reflect.ValueOf(s), Type: vm.TypeOf(s)}
i, ok := c.strings[s]
if !ok {
i = len(c.Data)
- c.Data = append(c.Data, vm.ValueOf(s))
+ c.Data = append(c.Data, v)
c.strings[s] = i
}
- push(&symbol{kind: symConst, value: vm.ValueOf(s)})
+ push(&symbol{kind: symConst, value: v})
emit(int64(t.Pos), vm.Dup, int64(i))
case lang.Add:
@@ -144,7 +145,11 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
// TODO: support assignment to local, composite objects.
st := tokens[i-1]
l := len(c.Data)
- typ := pop().Type
+ d := pop()
+ typ := d.Type
+ if typ == nil {
+ typ = d.value.Type
+ }
v := vm.NewValue(typ)
c.addSym(l, st.Str, v, symVar, typ, false)
c.Data = append(c.Data, v)
@@ -160,7 +165,11 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
if !ok {
return fmt.Errorf("symbol not found: %s", st.Str)
}
- typ := pop().Type
+ d := pop()
+ typ := d.Type
+ if typ == nil {
+ typ = d.value.Type
+ }
if s.Type == nil {
s.Type = typ
s.value = vm.NewValue(typ)
@@ -259,7 +268,7 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
} else {
i = s.value.Data.Int() - int64(len(c.Code))
}
- emit(int64(t.Pos), vm.JumpSetTrue, int64(i))
+ emit(int64(t.Pos), vm.JumpSetTrue, i)
case lang.Goto:
var i int64
@@ -431,17 +440,17 @@ type DumpValue struct {
// This design choice allows the Virtual Machine (VM) to evolve its memory management strategies
// without compromising backward compatibility with dumps generated by previous versions.
func (c *Compiler) Dump() *Dump {
- var dv []*DumpValue
dict := c.symbolsByIndex()
+ dv := make([]*DumpValue, len(c.Data))
for i, d := range c.Data {
e := dict[i]
- dv = append(dv, &DumpValue{
+ dv[i] = &DumpValue{
Index: e.index,
Name: e.name,
Kind: int(e.kind),
Type: e.Type.Name,
Value: d.Data.Interface(),
- })
+ }
}
return &Dump{Values: dv}