summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Vertes <mvertes@free.fr>2023-11-20 19:28:31 +0100
committerMarc Vertes <mvertes@free.fr>2023-11-20 19:28:31 +0100
commitae58deb5da1fa2ae5e461783ce592a9b962da778 (patch)
treede1d3bf4ce4ceea9c7386d191aecb6801b407ca0
parent6a0490257bf235d011004bc303306f617ac6ea31 (diff)
parser: add pointer support (work in progress)
This is incomplete because the scalar variables are not addressable right now. To be addressable they must be represented as reflect values, not interfaces.
-rw-r--r--parser/compiler.go6
-rw-r--r--parser/expr.go2
-rw-r--r--parser/interpreter_test.go7
-rw-r--r--parser/type.go9
4 files changed, 22 insertions, 2 deletions
diff --git a/parser/compiler.go b/parser/compiler.go
index bdf801b..36aa9d8 100644
--- a/parser/compiler.go
+++ b/parser/compiler.go
@@ -87,6 +87,12 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
case lang.Plus:
// Nothing to do.
+ case lang.Address:
+ emit(int64(t.Pos), vm.Address)
+
+ case lang.Deref:
+ emit(int64(t.Pos), vm.Deref)
+
case lang.Index:
emit(int64(t.Pos), vm.Index)
diff --git a/parser/expr.go b/parser/expr.go
index 207f38b..806fd75 100644
--- a/parser/expr.go
+++ b/parser/expr.go
@@ -42,7 +42,7 @@ func (p *Parser) ParseExpr(in Tokens) (out Tokens, err error) {
case lang.Int, lang.String:
out = append(out, t)
vl++
- case lang.Define, lang.Add, lang.Sub, lang.Assign, lang.Equal, lang.Greater, lang.Less, lang.Mul, lang.Land, lang.Lor, lang.Shl, lang.Shr, lang.Not:
+ case lang.Define, lang.Add, lang.Sub, lang.Assign, lang.Equal, lang.Greater, lang.Less, lang.Mul, lang.Land, lang.Lor, lang.Shl, lang.Shr, lang.Not, lang.And:
if i == 0 || in[i-1].Id.IsOperator() {
// An operator preceded by an operator or no token is unary.
t.Id = lang.UnaryOp[t.Id]
diff --git a/parser/interpreter_test.go b/parser/interpreter_test.go
index db9b916..9555475 100644
--- a/parser/interpreter_test.go
+++ b/parser/interpreter_test.go
@@ -192,6 +192,13 @@ func TestArray(t *testing.T) {
})
}
+func TestPointer(t *testing.T) {
+ run(t, []etest{
+ {src: "var a *int; a", res: "<nil>"},
+ //{src: "var a int = 2; var b *int = &a; b", res: "2"},
+ })
+}
+
func TestStruct(t *testing.T) {
run(t, []etest{
{src: "type T struct {a string; b, c int}; var t T; t", res: "{ 0 0}"},
diff --git a/parser/type.go b/parser/type.go
index 573ae6f..31af1e3 100644
--- a/parser/type.go
+++ b/parser/type.go
@@ -51,6 +51,13 @@ func (p *Parser) ParseTypeExpr(in Tokens) (typ reflect.Type, err error) {
}
return reflect.SliceOf(typ), nil
+ case lang.Mul:
+ typ, err := p.ParseTypeExpr(in[1:])
+ if err != nil {
+ return nil, err
+ }
+ return reflect.PointerTo(typ), nil
+
case lang.Func:
// Get argument and return token positions depending on function pattern:
// method with receiver, named function or anonymous closure.
@@ -165,7 +172,7 @@ func (p *Parser) parseParamTypes(in Tokens, flag typeFlag) (types []reflect.Type
func (p *Parser) addSymVar(index int, name string, typ reflect.Type, flag typeFlag, local bool) {
var zv any = reflect.New(typ).Elem()
switch typ.Kind() {
- case reflect.Struct, reflect.Array, reflect.Slice:
+ case reflect.Struct, reflect.Array, reflect.Slice, reflect.Pointer:
default:
zv = zv.(reflect.Value).Interface()
}