chagned Value_t to use unsafe.Pointer
This commit is contained in:
parent
ca5c1efd8a
commit
bff0c3b31d
@ -71,10 +71,10 @@ func main() {
|
||||
goto oops
|
||||
}
|
||||
|
||||
if v == nil {
|
||||
panic("return value mut not be nil")
|
||||
if v.Kind != pcl.VALUE_STR {
|
||||
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()
|
||||
f.Close()
|
||||
|
132
interp/eval.go
132
interp/eval.go
@ -2,12 +2,13 @@ package interp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var debug bool = false
|
||||
|
||||
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)
|
||||
@ -31,6 +32,7 @@ func (p *process_t) push_call_frame() {
|
||||
} else {
|
||||
cf.parent = p.cframe
|
||||
}
|
||||
cf.vars = make(map[string]Value_t)
|
||||
p.cframe = cf
|
||||
}
|
||||
|
||||
@ -47,7 +49,7 @@ func (p *process_t) push_cnode_value(val *Cnode_t) error {
|
||||
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.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")
|
||||
}
|
||||
|
||||
p.vstack[p.vsp] = &val
|
||||
p.vstack[p.vsp] = Value_t{Kind: VALUE_STR, V: unsafe.Pointer(&val)}
|
||||
p.vsp++
|
||||
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 {
|
||||
var new_val string
|
||||
var v1, v2 *string
|
||||
var ok1, ok2 bool
|
||||
var v1, v2 Value_t
|
||||
|
||||
if p.vsp < 2 {
|
||||
return fmt.Errorf("stack corrupt")
|
||||
}
|
||||
|
||||
v1, ok1 = p.vstack[p.vsp-2].(*string)
|
||||
v2, ok2 = p.vstack[p.vsp-1].(*string)
|
||||
v1 = p.vstack[p.vsp-2]
|
||||
v2 = p.vstack[p.vsp-1]
|
||||
|
||||
if !ok1 {
|
||||
// TODO: correct this to get the original text inside{}
|
||||
// or must panic here by making {} unmergable in the feeder side
|
||||
v1 = &empty_string
|
||||
if v1.Kind == VALUE_STR {
|
||||
new_val += *(*string)(v1.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
|
||||
// TODO: correct this to get the original text inside{}
|
||||
// or must panic here by making {} unmergable in the feeder side
|
||||
if v2.Kind == VALUE_STR {
|
||||
new_val += *(*string)(v2.V)
|
||||
}
|
||||
//new_val = *(*string)(p.vstack[p.vsp-2]) + *(*string)(p.vstack[p.vsp-1])
|
||||
new_val = *v1 + *v2
|
||||
|
||||
p.vsp--
|
||||
p.vstack[p.vsp] = nil
|
||||
p.vstack[p.vsp-1] = &new_val
|
||||
p.vstack[p.vsp].V = unsafe.Pointer(nil)
|
||||
p.vstack[p.vsp-1] = Value_t{Kind: VALUE_STR, V: unsafe.Pointer(&new_val)}
|
||||
p.ctx.count--
|
||||
|
||||
if debug {
|
||||
@ -106,7 +104,7 @@ func (p *process_t) pop_value() Value_t {
|
||||
var v Value_t
|
||||
p.vsp--
|
||||
v = p.vstack[p.vsp]
|
||||
p.vstack[p.vsp] = nil
|
||||
p.vstack[p.vsp].V = unsafe.Pointer(nil)
|
||||
return v
|
||||
}
|
||||
|
||||
@ -145,9 +143,7 @@ func (p *process_t) call() error {
|
||||
}
|
||||
|
||||
func (p *process_t) GetCalleeName() *string {
|
||||
var v *string
|
||||
v, _ = (p.vstack[p.vsp-p.ctx.count+1]).(*string)
|
||||
return v
|
||||
return (*string)(p.vstack[p.vsp-p.ctx.count+1].V)
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
@ -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???
|
||||
// clean up the unused part of the stack
|
||||
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
|
||||
@ -217,12 +213,12 @@ func (interp *Interp) dump_vstack(p *process_t) {
|
||||
// cnode value
|
||||
fmt.Printf(" %d => cnode %p", i, p.vstack[i]) // TODO: strip 1 off
|
||||
}*/
|
||||
switch t := p.vstack[i].(type) {
|
||||
case *string:
|
||||
fmt.Printf(" %d => [%s]\n", i, *t)
|
||||
case *Cnode_t:
|
||||
switch p.vstack[i].Kind {
|
||||
case VALUE_STR:
|
||||
fmt.Printf(" %d => [%s]\n", i, *(*string)(p.vstack[i].V))
|
||||
case VALUE_CNODE:
|
||||
fmt.Printf(" %d => ", i)
|
||||
interp.dump_cnodes(t, false)
|
||||
interp.dump_cnodes((*Cnode_t)(p.vstack[i].V), false)
|
||||
fmt.Printf("\n")
|
||||
default:
|
||||
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
|
||||
)
|
||||
|
||||
v = new(string) // TODO: change new(string) to a const
|
||||
v = empty_strval
|
||||
|
||||
upper_node = container_node
|
||||
stmt_node = upper_node.child // the first statement
|
||||
@ -422,31 +418,18 @@ done:
|
||||
return v, nil
|
||||
|
||||
oops:
|
||||
return nil, err
|
||||
return empty_strval, err
|
||||
}
|
||||
|
||||
func (interp *Interp) eval_arg(p *process_t, pos int) (Value_t, error) {
|
||||
/*
|
||||
var (
|
||||
ptr uintptr
|
||||
)
|
||||
var v Value_t
|
||||
|
||||
ptr = uintptr(p.GetArg(pos))
|
||||
if ptr&1 == 1 { // cnode
|
||||
ptr &= ^uintptr(1)
|
||||
//interp.dump_cnodes((*Cnode_t)(unsafe.Pointer(ptr)), true)
|
||||
//return interp.eval_atom_node((*Cnode_t)(unsafe.Pointer(ptr)).child)
|
||||
return interp.eval_stmt_nodes((*Cnode_t)(unsafe.Pointer(ptr)))
|
||||
} 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)
|
||||
v = p.GetArg(pos)
|
||||
switch v.Kind {
|
||||
case VALUE_STR:
|
||||
return v, nil
|
||||
case VALUE_CNODE:
|
||||
return interp.eval_stmt_nodes(p, (*Cnode_t)(v.V))
|
||||
default:
|
||||
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
|
||||
}*/
|
||||
|
||||
switch t := p.GetArg(pos).(type) {
|
||||
case *string:
|
||||
return t, nil
|
||||
case *Cnode_t:
|
||||
var v Value_t
|
||||
|
||||
v = p.GetArg(pos)
|
||||
switch v.Kind {
|
||||
case VALUE_STR:
|
||||
return v, nil
|
||||
case VALUE_CNODE:
|
||||
// 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:
|
||||
panic("internal error - argument type unrecognized")
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
var (
|
||||
v Value_t
|
||||
@ -517,5 +531,5 @@ func (interp *Interp) EvalText(text []rune) (Value_t, error) {
|
||||
return v, nil
|
||||
|
||||
oops:
|
||||
return nil, err
|
||||
return empty_strval, err
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package interp
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type error_t struct {
|
||||
@ -39,7 +40,17 @@ type context_t struct {
|
||||
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 {
|
||||
interp *Interp
|
||||
@ -50,7 +61,7 @@ type process_t struct {
|
||||
}
|
||||
|
||||
type call_frame_t struct {
|
||||
vars *Var
|
||||
vars map[string]Value_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.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 {
|
||||
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
|
||||
@ -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_stmt_nodes(&p, node)
|
||||
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) {
|
||||
|
@ -69,8 +69,6 @@ func proc_expr(p *process_t) error {
|
||||
func proc_if(p *process_t) error {
|
||||
var (
|
||||
v Value_t
|
||||
vv *string
|
||||
ok bool
|
||||
err error
|
||||
)
|
||||
|
||||
@ -85,11 +83,10 @@ func proc_if(p *process_t) error {
|
||||
goto done
|
||||
}
|
||||
|
||||
vv, ok = v.(*string)
|
||||
if !ok {
|
||||
if v.Kind != VALUE_STR {
|
||||
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_arg(p, 1)
|
||||
if err != nil {
|
||||
@ -110,7 +107,6 @@ func proc_puts(p *process_t) error {
|
||||
i int
|
||||
nargs int
|
||||
v Value_t
|
||||
vv *string
|
||||
err error
|
||||
)
|
||||
|
||||
@ -126,8 +122,11 @@ func proc_puts(p *process_t) error {
|
||||
return err
|
||||
}
|
||||
|
||||
vv, _ = v.(*string)
|
||||
fmt.Printf("%s", *vv)
|
||||
// TODO: check if v.kind is VALUE_STR
|
||||
if v.Kind != VALUE_STR {
|
||||
panic("internal error... invalid evaluation resutl")
|
||||
}
|
||||
fmt.Printf("%s", *(*string)(v.V))
|
||||
}
|
||||
|
||||
if nargs >= 1 {
|
||||
|
Loading…
Reference in New Issue
Block a user