chagned Value_t to use unsafe.Pointer
This commit is contained in:
parent
ca5c1efd8a
commit
bff0c3b31d
@ -71,10 +71,10 @@ func main() {
|
|||||||
goto oops
|
goto oops
|
||||||
}
|
}
|
||||||
|
|
||||||
if v == nil {
|
if v.Kind != pcl.VALUE_STR {
|
||||||
panic("return value mut not be nil")
|
panic("return value must not be string")
|
||||||
}
|
}
|
||||||
fmt.Printf("RETURN VALUE = [%s]\n", *v.(*string))
|
fmt.Printf("RETURN VALUE = [%s]\n", *(*string)(v.V))
|
||||||
|
|
||||||
interp.Close()
|
interp.Close()
|
||||||
f.Close()
|
f.Close()
|
||||||
|
130
interp/eval.go
130
interp/eval.go
@ -2,12 +2,13 @@ package interp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
var debug bool = false
|
var debug bool = false
|
||||||
|
|
||||||
var err_num_args *error_t = &error_t{msg: "wrong number of arguments"}
|
var err_num_args *error_t = &error_t{msg: "wrong number of arguments"}
|
||||||
var empty_string = ""
|
var empty_strval = Value_t{Kind: VALUE_STR, V: unsafe.Pointer(new(string))}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
value stack (p.vstack)
|
value stack (p.vstack)
|
||||||
@ -31,6 +32,7 @@ func (p *process_t) push_call_frame() {
|
|||||||
} else {
|
} else {
|
||||||
cf.parent = p.cframe
|
cf.parent = p.cframe
|
||||||
}
|
}
|
||||||
|
cf.vars = make(map[string]Value_t)
|
||||||
p.cframe = cf
|
p.cframe = cf
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +49,7 @@ func (p *process_t) push_cnode_value(val *Cnode_t) error {
|
|||||||
return fmt.Errorf("stack full")
|
return fmt.Errorf("stack full")
|
||||||
}
|
}
|
||||||
|
|
||||||
p.vstack[p.vsp] = val
|
p.vstack[p.vsp] = Value_t{Kind: VALUE_CNODE, V: unsafe.Pointer(val)}
|
||||||
p.vsp++
|
p.vsp++
|
||||||
p.ctx.count++
|
p.ctx.count++
|
||||||
//fmt.Printf("push_cnode_value = ctx.count => %d\n", p.ctx.count)
|
//fmt.Printf("push_cnode_value = ctx.count => %d\n", p.ctx.count)
|
||||||
@ -60,7 +62,7 @@ func (p *process_t) push_string_value(val string) error {
|
|||||||
return fmt.Errorf("stack full")
|
return fmt.Errorf("stack full")
|
||||||
}
|
}
|
||||||
|
|
||||||
p.vstack[p.vsp] = &val
|
p.vstack[p.vsp] = Value_t{Kind: VALUE_STR, V: unsafe.Pointer(&val)}
|
||||||
p.vsp++
|
p.vsp++
|
||||||
p.ctx.count++
|
p.ctx.count++
|
||||||
//fmt.Printf("push_string_value = ctx.count => %d\n", p.ctx.count)
|
//fmt.Printf("push_string_value = ctx.count => %d\n", p.ctx.count)
|
||||||
@ -69,31 +71,27 @@ func (p *process_t) push_string_value(val string) error {
|
|||||||
|
|
||||||
func (p *process_t) merge_top_values() error {
|
func (p *process_t) merge_top_values() error {
|
||||||
var new_val string
|
var new_val string
|
||||||
var v1, v2 *string
|
var v1, v2 Value_t
|
||||||
var ok1, ok2 bool
|
|
||||||
|
|
||||||
if p.vsp < 2 {
|
if p.vsp < 2 {
|
||||||
return fmt.Errorf("stack corrupt")
|
return fmt.Errorf("stack corrupt")
|
||||||
}
|
}
|
||||||
|
|
||||||
v1, ok1 = p.vstack[p.vsp-2].(*string)
|
v1 = p.vstack[p.vsp-2]
|
||||||
v2, ok2 = p.vstack[p.vsp-1].(*string)
|
v2 = p.vstack[p.vsp-1]
|
||||||
|
|
||||||
if !ok1 {
|
if v1.Kind == VALUE_STR {
|
||||||
|
new_val += *(*string)(v1.V)
|
||||||
|
}
|
||||||
// TODO: correct this to get the original text inside{}
|
// TODO: correct this to get the original text inside{}
|
||||||
// or must panic here by making {} unmergable in the feeder side
|
// or must panic here by making {} unmergable in the feeder side
|
||||||
v1 = &empty_string
|
if v2.Kind == VALUE_STR {
|
||||||
|
new_val += *(*string)(v2.V)
|
||||||
}
|
}
|
||||||
if !ok2 {
|
|
||||||
// TODO: correct this to get the original text inside {}
|
|
||||||
// or must panic here by making {} unmergable in the feeder side
|
|
||||||
v2 = &empty_string
|
|
||||||
}
|
|
||||||
//new_val = *(*string)(p.vstack[p.vsp-2]) + *(*string)(p.vstack[p.vsp-1])
|
|
||||||
new_val = *v1 + *v2
|
|
||||||
p.vsp--
|
p.vsp--
|
||||||
p.vstack[p.vsp] = nil
|
p.vstack[p.vsp].V = unsafe.Pointer(nil)
|
||||||
p.vstack[p.vsp-1] = &new_val
|
p.vstack[p.vsp-1] = Value_t{Kind: VALUE_STR, V: unsafe.Pointer(&new_val)}
|
||||||
p.ctx.count--
|
p.ctx.count--
|
||||||
|
|
||||||
if debug {
|
if debug {
|
||||||
@ -106,7 +104,7 @@ func (p *process_t) pop_value() Value_t {
|
|||||||
var v Value_t
|
var v Value_t
|
||||||
p.vsp--
|
p.vsp--
|
||||||
v = p.vstack[p.vsp]
|
v = p.vstack[p.vsp]
|
||||||
p.vstack[p.vsp] = nil
|
p.vstack[p.vsp].V = unsafe.Pointer(nil)
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,9 +143,7 @@ func (p *process_t) call() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *process_t) GetCalleeName() *string {
|
func (p *process_t) GetCalleeName() *string {
|
||||||
var v *string
|
return (*string)(p.vstack[p.vsp-p.ctx.count+1].V)
|
||||||
v, _ = (p.vstack[p.vsp-p.ctx.count+1]).(*string)
|
|
||||||
return v
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *process_t) GetArg(idx int) Value_t {
|
func (p *process_t) GetArg(idx int) Value_t {
|
||||||
@ -159,7 +155,7 @@ func (p *process_t) GetNumArgs() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *process_t) ReturnString(val string) {
|
func (p *process_t) ReturnString(val string) {
|
||||||
p.vstack[p.vsp-p.ctx.count] = &val
|
p.vstack[p.vsp-p.ctx.count] = Value_t{Kind: VALUE_STR, V: unsafe.Pointer(&val)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *process_t) Return(val Value_t) {
|
func (p *process_t) Return(val Value_t) {
|
||||||
@ -190,7 +186,7 @@ func (p *process_t) pop_context(clear_vstack bool) (*Cnode_t, *Cnode_t) {
|
|||||||
if clear_vstack { // TODO: use the conttext type instead... may be able to use container_node.code???
|
if clear_vstack { // TODO: use the conttext type instead... may be able to use container_node.code???
|
||||||
// clean up the unused part of the stack
|
// clean up the unused part of the stack
|
||||||
for i = 1; i < p.ctx.count; i++ {
|
for i = 1; i < p.ctx.count; i++ {
|
||||||
p.vstack[p.vsp-p.ctx.count+i] = nil
|
p.vstack[p.vsp-p.ctx.count+i].V = unsafe.Pointer(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pop off the cleaned arguments
|
// pop off the cleaned arguments
|
||||||
@ -217,12 +213,12 @@ func (interp *Interp) dump_vstack(p *process_t) {
|
|||||||
// cnode value
|
// cnode value
|
||||||
fmt.Printf(" %d => cnode %p", i, p.vstack[i]) // TODO: strip 1 off
|
fmt.Printf(" %d => cnode %p", i, p.vstack[i]) // TODO: strip 1 off
|
||||||
}*/
|
}*/
|
||||||
switch t := p.vstack[i].(type) {
|
switch p.vstack[i].Kind {
|
||||||
case *string:
|
case VALUE_STR:
|
||||||
fmt.Printf(" %d => [%s]\n", i, *t)
|
fmt.Printf(" %d => [%s]\n", i, *(*string)(p.vstack[i].V))
|
||||||
case *Cnode_t:
|
case VALUE_CNODE:
|
||||||
fmt.Printf(" %d => ", i)
|
fmt.Printf(" %d => ", i)
|
||||||
interp.dump_cnodes(t, false)
|
interp.dump_cnodes((*Cnode_t)(p.vstack[i].V), false)
|
||||||
fmt.Printf("\n")
|
fmt.Printf("\n")
|
||||||
default:
|
default:
|
||||||
panic("internal error - unrecognized value")
|
panic("internal error - unrecognized value")
|
||||||
@ -265,7 +261,7 @@ func (interp *Interp) eval_stmt_nodes(p *process_t, container_node *Cnode_t) (Va
|
|||||||
org_vsp int
|
org_vsp int
|
||||||
)
|
)
|
||||||
|
|
||||||
v = new(string) // TODO: change new(string) to a const
|
v = empty_strval
|
||||||
|
|
||||||
upper_node = container_node
|
upper_node = container_node
|
||||||
stmt_node = upper_node.child // the first statement
|
stmt_node = upper_node.child // the first statement
|
||||||
@ -422,31 +418,18 @@ done:
|
|||||||
return v, nil
|
return v, nil
|
||||||
|
|
||||||
oops:
|
oops:
|
||||||
return nil, err
|
return empty_strval, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (interp *Interp) eval_arg(p *process_t, pos int) (Value_t, error) {
|
func (interp *Interp) eval_arg(p *process_t, pos int) (Value_t, error) {
|
||||||
/*
|
var v Value_t
|
||||||
var (
|
|
||||||
ptr uintptr
|
|
||||||
)
|
|
||||||
|
|
||||||
ptr = uintptr(p.GetArg(pos))
|
v = p.GetArg(pos)
|
||||||
if ptr&1 == 1 { // cnode
|
switch v.Kind {
|
||||||
ptr &= ^uintptr(1)
|
case VALUE_STR:
|
||||||
//interp.dump_cnodes((*Cnode_t)(unsafe.Pointer(ptr)), true)
|
return v, nil
|
||||||
//return interp.eval_atom_node((*Cnode_t)(unsafe.Pointer(ptr)).child)
|
case VALUE_CNODE:
|
||||||
return interp.eval_stmt_nodes((*Cnode_t)(unsafe.Pointer(ptr)))
|
return interp.eval_stmt_nodes(p, (*Cnode_t)(v.V))
|
||||||
} else {
|
|
||||||
return (*string)(unsafe.Pointer(ptr)), nil
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
switch t := p.GetArg(pos).(type) {
|
|
||||||
case *string:
|
|
||||||
return t, nil
|
|
||||||
case *Cnode_t:
|
|
||||||
return interp.eval_stmt_nodes(p, t)
|
|
||||||
default:
|
default:
|
||||||
panic("internal error - argument type unrecognized")
|
panic("internal error - argument type unrecognized")
|
||||||
}
|
}
|
||||||
@ -469,23 +452,54 @@ func (interp *Interp) eval_arg_literally(p *process_t, pos int) (Value_t, error)
|
|||||||
return (*string)(unsafe.Pointer(ptr)), nil
|
return (*string)(unsafe.Pointer(ptr)), nil
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
switch t := p.GetArg(pos).(type) {
|
var v Value_t
|
||||||
case *string:
|
|
||||||
return t, nil
|
v = p.GetArg(pos)
|
||||||
case *Cnode_t:
|
switch v.Kind {
|
||||||
|
case VALUE_STR:
|
||||||
|
return v, nil
|
||||||
|
case VALUE_CNODE:
|
||||||
// TODO: can support this? by storing the original text?
|
// TODO: can support this? by storing the original text?
|
||||||
return nil, fmt.Errorf("not supported - unable to evaluate {} literally")
|
return empty_strval, fmt.Errorf("not supported - unable to evaluate {} literally")
|
||||||
default:
|
default:
|
||||||
panic("internal error - argument type unrecognized")
|
panic("internal error - argument type unrecognized")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (interp *Interp) set_var(p *process_t, name Value_t, val Value_t) error {
|
func (interp *Interp) set_var(p *process_t, name Value_t, val Value_t) error {
|
||||||
//var err error_t
|
if name.Kind != VALUE_STR {
|
||||||
|
return fmt.Errorf("invalid variable name")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: error check?
|
||||||
|
p.cframe.vars[*(*string)(name.V)] = val
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (interp *Interp) get_var(p *process_t, name Value_t) (Value_t, error) {
|
||||||
|
var (
|
||||||
|
key *string
|
||||||
|
val Value_t
|
||||||
|
f *call_frame_t
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
|
||||||
|
if name.Kind != VALUE_STR {
|
||||||
|
return empty_strval, fmt.Errorf("invalid variable name")
|
||||||
|
}
|
||||||
|
|
||||||
|
key = (*string)(name.V)
|
||||||
|
|
||||||
|
for f = p.cframe; f != nil; f = f.parent {
|
||||||
|
val, ok = p.cframe.vars[*key]
|
||||||
|
if ok {
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return empty_strval, fmt.Errorf("%s not found", *key)
|
||||||
|
}
|
||||||
|
|
||||||
func (interp *Interp) EvalText(text []rune) (Value_t, error) {
|
func (interp *Interp) EvalText(text []rune) (Value_t, error) {
|
||||||
var (
|
var (
|
||||||
v Value_t
|
v Value_t
|
||||||
@ -517,5 +531,5 @@ func (interp *Interp) EvalText(text []rune) (Value_t, error) {
|
|||||||
return v, nil
|
return v, nil
|
||||||
|
|
||||||
oops:
|
oops:
|
||||||
return nil, err
|
return empty_strval, err
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package interp
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
type error_t struct {
|
type error_t struct {
|
||||||
@ -39,7 +40,17 @@ type context_t struct {
|
|||||||
container_node *Cnode_t
|
container_node *Cnode_t
|
||||||
}
|
}
|
||||||
|
|
||||||
type Value_t interface{}
|
type ValueKind int
|
||||||
|
|
||||||
|
const (
|
||||||
|
VALUE_STR ValueKind = iota
|
||||||
|
VALUE_CNODE
|
||||||
|
)
|
||||||
|
|
||||||
|
type Value_t struct {
|
||||||
|
Kind ValueKind
|
||||||
|
V unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
type process_t struct {
|
type process_t struct {
|
||||||
interp *Interp
|
interp *Interp
|
||||||
@ -50,7 +61,7 @@ type process_t struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type call_frame_t struct {
|
type call_frame_t struct {
|
||||||
vars *Var
|
vars map[string]Value_t
|
||||||
parent *call_frame_t
|
parent *call_frame_t
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,12 +254,14 @@ func (interp *Interp) Execute(node_head *Cnode_t) (Value_t, error) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
p = process_t{interp: interp, vsp: 0}
|
p = process_t{interp: interp, vsp: 0}
|
||||||
|
p.push_call_frame()
|
||||||
|
|
||||||
v = new(string) // if there is no code the execute, the return value is an empty string
|
v = empty_strval // if there is no code the execute, the return value is an empty string
|
||||||
|
err = nil
|
||||||
|
|
||||||
for node = node_head; node != nil; node = node.next {
|
for node = node_head; node != nil; node = node.next {
|
||||||
if node.code != CNODE_INIT {
|
if node.code != CNODE_INIT {
|
||||||
return nil, fmt.Errorf("non-init node")
|
return empty_strval, fmt.Errorf("non-init node")
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.child == nil { // TODO: optmize the cnode tree that this check is not needed. the reader must not create an INIT node with empty
|
if node.child == nil { // TODO: optmize the cnode tree that this check is not needed. the reader must not create an INIT node with empty
|
||||||
@ -258,11 +271,16 @@ func (interp *Interp) Execute(node_head *Cnode_t) (Value_t, error) {
|
|||||||
//v, err = interp.eval_node_child(node.child)
|
//v, err = interp.eval_node_child(node.child)
|
||||||
v, err = interp.eval_stmt_nodes(&p, node)
|
v, err = interp.eval_stmt_nodes(&p, node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
goto done
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return v, nil
|
done:
|
||||||
|
// if there is no error, p.cframe must point to the global call frame here.
|
||||||
|
for p.cframe != nil {
|
||||||
|
p.pop_call_frame()
|
||||||
|
}
|
||||||
|
return v, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (interp *Interp) dump_cnodes(node *Cnode_t, nl bool) {
|
func (interp *Interp) dump_cnodes(node *Cnode_t, nl bool) {
|
||||||
|
@ -69,8 +69,6 @@ func proc_expr(p *process_t) error {
|
|||||||
func proc_if(p *process_t) error {
|
func proc_if(p *process_t) error {
|
||||||
var (
|
var (
|
||||||
v Value_t
|
v Value_t
|
||||||
vv *string
|
|
||||||
ok bool
|
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -85,11 +83,10 @@ func proc_if(p *process_t) error {
|
|||||||
goto done
|
goto done
|
||||||
}
|
}
|
||||||
|
|
||||||
vv, ok = v.(*string)
|
if v.Kind != VALUE_STR {
|
||||||
if !ok {
|
|
||||||
panic("internal error - screwed conditional value")
|
panic("internal error - screwed conditional value")
|
||||||
}
|
}
|
||||||
if *vv != "" {
|
if *(*string)(v.V) != "" {
|
||||||
//v, err = p.interp.eval_atom_node((*Cnode_t)(p.GetArg(1)))
|
//v, err = p.interp.eval_atom_node((*Cnode_t)(p.GetArg(1)))
|
||||||
v, err = p.interp.eval_arg(p, 1)
|
v, err = p.interp.eval_arg(p, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -110,7 +107,6 @@ func proc_puts(p *process_t) error {
|
|||||||
i int
|
i int
|
||||||
nargs int
|
nargs int
|
||||||
v Value_t
|
v Value_t
|
||||||
vv *string
|
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -126,8 +122,11 @@ func proc_puts(p *process_t) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
vv, _ = v.(*string)
|
// TODO: check if v.kind is VALUE_STR
|
||||||
fmt.Printf("%s", *vv)
|
if v.Kind != VALUE_STR {
|
||||||
|
panic("internal error... invalid evaluation resutl")
|
||||||
|
}
|
||||||
|
fmt.Printf("%s", *(*string)(v.V))
|
||||||
}
|
}
|
||||||
|
|
||||||
if nargs >= 1 {
|
if nargs >= 1 {
|
||||||
|
Loading…
Reference in New Issue
Block a user