defined the value type Value_t to be interface{} in place of unsafe.Pointer

This commit is contained in:
hyung-hwan 2023-08-04 18:41:30 +09:00
parent 1ad6779aa4
commit 3cae246546
4 changed files with 153 additions and 85 deletions

View File

@ -16,8 +16,9 @@ func main() {
r *bufio.Reader r *bufio.Reader
c rune c rune
node *pcl.Cnode_t node *pcl.Cnode_t
v *string v pcl.Value_t
err error
err error
) )
if len(os.Args) != 2 { if len(os.Args) != 2 {
@ -73,7 +74,7 @@ func main() {
if v == nil { if v == nil {
panic("return value mut not be nil") panic("return value mut not be nil")
} }
fmt.Printf("RETURN VALUE = [%s]\n", *v) fmt.Printf("RETURN VALUE = [%s]\n", *v.(*string))
/* /*
err = interp.FeedRunes([]rune(` err = interp.FeedRunes([]rune(`

View File

@ -5,7 +5,7 @@ import (
"unsafe" "unsafe"
) )
var debug bool = true 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"}
@ -26,12 +26,10 @@ func (p *process_t) push_cnode_value(val *Cnode_t) error {
return fmt.Errorf("stack full") return fmt.Errorf("stack full")
} }
// TODO: using the last bit won't be compatible with go's GC. p.vstack[p.vsp] = val
// CHANGE to use inteface{} or devise a different scheme...
p.vstack[p.vsp] = unsafe.Pointer(uintptr(unsafe.Pointer(val)) | 1)
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)
return nil return nil
} }
@ -41,30 +39,38 @@ func (p *process_t) push_string_value(val string) error {
return fmt.Errorf("stack full") return fmt.Errorf("stack full")
} }
p.vstack[p.vsp] = unsafe.Pointer(&val) p.vstack[p.vsp] = &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)
return nil return nil
} }
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
if p.vsp < 2 { if p.vsp < 2 {
return fmt.Errorf("stack corrupt") return fmt.Errorf("stack corrupt")
} }
new_val = *(*string)(p.vstack[p.vsp-2]) + *(*string)(p.vstack[p.vsp-1])
v1, _ = p.vstack[p.vsp-2].(*string)
v2, _ = p.vstack[p.vsp-1].(*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] = nil
p.vstack[p.vsp-1] = unsafe.Pointer(&new_val) p.vstack[p.vsp-1] = unsafe.Pointer(&new_val)
p.ctx.count-- p.ctx.count--
fmt.Printf("merge_top_values = ctx.count => %d\n", p.ctx.count)
if debug {
fmt.Printf("merge_top_values = ctx.count => %d\n", p.ctx.count)
}
return nil return nil
} }
func (p *process_t) pop_value() unsafe.Pointer { func (p *process_t) pop_value() Value_t {
var v unsafe.Pointer 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] = nil
@ -78,6 +84,11 @@ func (p *process_t) call() error {
) )
callee = p.GetCalleeName() callee = p.GetCalleeName()
if debug {
fmt.Printf("calling..... [%s]\n", *callee)
}
// TODO: use a map // TODO: use a map
switch *callee { switch *callee {
case "if": case "if":
@ -97,10 +108,12 @@ func (p *process_t) call() error {
} }
func (p *process_t) GetCalleeName() *string { func (p *process_t) GetCalleeName() *string {
return (*string)(p.vstack[p.vsp-p.ctx.count+1]) var v *string
v, _ = (p.vstack[p.vsp-p.ctx.count+1]).(*string)
return v
} }
func (p *process_t) GetArg(idx int) unsafe.Pointer { func (p *process_t) GetArg(idx int) Value_t {
return (p.vstack[p.vsp-p.ctx.count+2+idx]) return (p.vstack[p.vsp-p.ctx.count+2+idx])
} }
@ -108,11 +121,14 @@ func (p *process_t) GetNumArgs() int {
return p.ctx.count - 2 return p.ctx.count - 2
} }
func (p *process_t) Return(val string) { func (p *process_t) Return(val Value_t) {
p.vstack[p.vsp-p.ctx.count] = unsafe.Pointer(&val) p.vstack[p.vsp-p.ctx.count] = val
} }
func (p *process_t) push_context(node *Cnode_t, container_node *Cnode_t) { func (p *process_t) push_context(node *Cnode_t, container_node *Cnode_t) {
if debug {
fmt.Printf("PUSHING CONTEXT.....\n")
}
p.ctx = &context_t{count: 0, parent_ctx: p.ctx, parent_node: node, container_node: container_node} p.ctx = &context_t{count: 0, parent_ctx: p.ctx, parent_node: node, container_node: container_node}
} }
@ -123,6 +139,10 @@ func (p *process_t) pop_context(clear_vstack bool) (*Cnode_t, *Cnode_t) {
container *Cnode_t container *Cnode_t
) )
if debug {
fmt.Printf("POPPING CONTEXT.....is_stmt/clear_vstack[%v]\n", clear_vstack)
}
node = p.ctx.parent_node node = p.ctx.parent_node
container = p.ctx.container_node container = p.ctx.container_node
@ -137,9 +157,9 @@ func (p *process_t) pop_context(clear_vstack bool) (*Cnode_t, *Cnode_t) {
} }
p.ctx = p.ctx.parent_ctx p.ctx = p.ctx.parent_ctx
// if p.ctx != nil { // if p.ctx != nil {
// p.ctx.count++ // let the return value be the argument to the caller // p.ctx.count++ // let the return value be the argument to the caller
// } // }
return node, container return node, container
} }
@ -147,13 +167,24 @@ func (p *process_t) pop_context(clear_vstack bool) (*Cnode_t, *Cnode_t) {
func (interp *Interp) dump_vstack(p *process_t) { func (interp *Interp) dump_vstack(p *process_t) {
fmt.Printf("p.VSP => %d\n", p.vsp) fmt.Printf("p.VSP => %d\n", p.vsp)
for i := 0; i < p.vsp; i++ { for i := 0; i < p.vsp; i++ {
x := uintptr(p.vstack[i]) /*
if x&1 == 0 { x := uintptr(p.vstack[i])
// string value if x&1 == 0 {
fmt.Printf(" %d => [%s]\n", i, *(*string)(p.vstack[i])) // string value
} else { fmt.Printf(" %d => [%s]\n", i, *(*string)(p.vstack[i]))
// cnode value } else {
fmt.Printf(" %d => cnode %p", i, p.vstack[i]) // TODO: strip 1 off // 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:
fmt.Printf(" %d => ", i)
interp.dump_cnodes(t, false)
fmt.Printf("\n")
default:
panic("internal error - unrecognized value")
} }
} }
} }
@ -182,15 +213,16 @@ puts "hello" world
[STMT] [STMT]
[TEXT|null] [TEXT|1] [TEXT|null] [TEXT|1]
*/ */
func (interp *Interp) eval_stmt_nodes(container_node *Cnode_t) (*string, error) { func (interp *Interp) eval_stmt_nodes(container_node *Cnode_t) (Value_t, error) {
var ( var (
p process_t p process_t
v *string v Value_t
stmt_node *Cnode_t stmt_node *Cnode_t
upper_node *Cnode_t upper_node *Cnode_t
inner_node *Cnode_t inner_node *Cnode_t
is_stmt bool is_stmt bool
err error err error
org_vsp int
) )
v = new(string) // TODO: change new(string) to a const v = new(string) // TODO: change new(string) to a const
@ -199,19 +231,22 @@ func (interp *Interp) eval_stmt_nodes(container_node *Cnode_t) (*string, error)
upper_node = container_node upper_node = container_node
stmt_node = upper_node.child // the first statement stmt_node = upper_node.child // the first statement
org_vsp = p.vsp
fmt.Printf("START p.sp = %d\n", p.vsp) fmt.Printf("START p.sp = %d\n", p.vsp)
for stmt_node != nil { if stmt_node == nil {
goto done
}
for {
start_over_0: start_over_0:
if stmt_node.code != CNODE_STMT { if stmt_node.code != CNODE_STMT {
panic("internal error - not statement node") panic("internal error - not statement node")
} }
fmt.Printf("PUSHING CONTEXT.....\n")
p.push_context(stmt_node, upper_node) p.push_context(stmt_node, upper_node)
p.push_string_value("") // placeholder for return value p.push_string_value("") // placeholder for return value
//start_over:
inner_node = stmt_node.child inner_node = stmt_node.child
resume: resume:
for inner_node != nil { for inner_node != nil {
@ -235,7 +270,6 @@ func (interp *Interp) eval_stmt_nodes(container_node *Cnode_t) (*string, error)
case CNODE_DQUOTE: case CNODE_DQUOTE:
if inner_node.child != nil { if inner_node.child != nil {
fmt.Printf("PUSHING CONTEXT.....\n")
p.push_context(stmt_node, inner_node) p.push_context(stmt_node, inner_node)
//p.push_string_value("") // no placeholder for return value is needed //p.push_string_value("") // no placeholder for return value is needed
inner_node = inner_node.child inner_node = inner_node.child
@ -264,6 +298,9 @@ func (interp *Interp) eval_stmt_nodes(container_node *Cnode_t) (*string, error)
// TODO: many more types... // TODO: many more types...
case CNODE_JOIN: case CNODE_JOIN:
p.merge_top_values() p.merge_top_values()
case CNODE_INIT:
panic("internal error - INIT node must not appear inside a statement")
} }
inner_node = inner_node.next inner_node = inner_node.next
@ -273,10 +310,7 @@ func (interp *Interp) eval_stmt_nodes(container_node *Cnode_t) (*string, error)
interp.dump_vstack(&p) interp.dump_vstack(&p)
} }
//fmt.Printf("p.ctx.parent_node.code %d p.ctx.container_node.code %d CNODE_STMT %d CNODE_DQUOTE %d CNODE_BRACKET %d\n", p.ctx.parent_node.code, p.ctx.container_node.code, CNODE_STMT, CNODE_DQUOTE, CNODE_BRACKET) //fmt.Printf("p.ctx.parent_node.code %d p.ctx.container_node.code %d CNODE_STMT %d CNODE_DQUOTE %d CNODE_BRACKET %d\n", p.ctx.parent_node.code, p.ctx.container_node.code, CNODE_STMT, CNODE_DQUOTE, CNODE_BRACKET)
if p.ctx.container_node.code == CNODE_INIT || p.ctx.container_node.code == CNODE_BRACKET { if p.ctx.container_node.code == CNODE_INIT || p.ctx.container_node.code == CNODE_BRACKET || p.ctx.container_node.code == CNODE_BRACE {
if debug {
fmt.Printf("calling..... [%s]\n", *p.GetCalleeName())
}
err = p.call() err = p.call()
if err != nil { if err != nil {
goto oops goto oops
@ -287,7 +321,6 @@ func (interp *Interp) eval_stmt_nodes(container_node *Cnode_t) (*string, error)
is_stmt = false is_stmt = false
} }
fmt.Printf("POPPING CONTEXT.....is_stmt[%v]\n", is_stmt)
stmt_node, upper_node = p.pop_context(is_stmt) stmt_node, upper_node = p.pop_context(is_stmt)
if upper_node != container_node { if upper_node != container_node {
if debug { if debug {
@ -296,7 +329,7 @@ func (interp *Interp) eval_stmt_nodes(container_node *Cnode_t) (*string, error)
if upper_node.code != CNODE_BRACKET { if upper_node.code != CNODE_BRACKET {
inner_node = upper_node.next // as if it hit the bottom of the innner for loop inner_node = upper_node.next // as if it hit the bottom of the innner for loop
p.ctx.count++; // use return value on the stack as an argument p.ctx.count++ // use return value on the stack as an argument
goto resume goto resume
} }
} }
@ -317,76 +350,100 @@ func (interp *Interp) eval_stmt_nodes(container_node *Cnode_t) (*string, error)
if upper_node.code != CNODE_BRACKET { if upper_node.code != CNODE_BRACKET {
panic("internal error - invalid cnode type in the context statck") panic("internal error - invalid cnode type in the context statck")
} }
fmt.Printf("POPPING CONTEXT.....false\n")
//stmt_node, upper_node = p.pop_context(false)
inner_node = upper_node.next
fmt.Printf(">>>>>>>>>>>>>>>>>> vsp %d ctx.count %d\n", p.vsp, p.ctx.count)
p.ctx.count++; // use the result value as an argument inner_node = upper_node.next
//fmt.Printf(">>>>>>>>>>>>>>>>>> vsp %d ctx.count %d\n", p.vsp, p.ctx.count)
p.ctx.count++ // use the result value as an argument
goto resume goto resume
} }
fmt.Printf("POPVAL...\n") v = p.pop_value() // get the return value of the statement.
v = (*string)(p.pop_value()) // get the return value of the statement.
if debug { if debug {
interp.dump_vstack(&p) interp.dump_vstack(&p)
} }
break break
} }
fmt.Printf("POPVAL...\n") v = p.pop_value() // get the return value of the statement.
v = (*string)(p.pop_value()) // get the return value of the statement.
if debug { if debug {
interp.dump_vstack(&p) interp.dump_vstack(&p)
} }
} }
done:
if debug { if debug {
interp.dump_vstack(&p) interp.dump_vstack(&p)
fmt.Printf("END p.sp = %d\n", p.vsp) fmt.Printf("END p.sp = %d\n", p.vsp)
} }
if p.vsp != org_vsp {
panic("internal error - stack not clean")
}
return v, nil return v, nil
oops: oops:
return nil, err return nil, err
} }
func (interp *Interp) eval_arg(p *process_t, pos int) (*string, error) { func (interp *Interp) eval_arg(p *process_t, pos int) (Value_t, error) {
var ( /*
ptr uintptr var (
) ptr uintptr
)
ptr = uintptr(p.GetArg(pos)) ptr = uintptr(p.GetArg(pos))
if ptr&1 == 1 { // cnode if ptr&1 == 1 { // cnode
ptr &= ^uintptr(1) ptr &= ^uintptr(1)
//interp.dump_cnodes((*Cnode_t)(unsafe.Pointer(ptr)), true) //interp.dump_cnodes((*Cnode_t)(unsafe.Pointer(ptr)), true)
//return interp.eval_atom_node((*Cnode_t)(unsafe.Pointer(ptr)).child) //return interp.eval_atom_node((*Cnode_t)(unsafe.Pointer(ptr)).child)
return interp.eval_stmt_nodes((*Cnode_t)(unsafe.Pointer(ptr))) return interp.eval_stmt_nodes((*Cnode_t)(unsafe.Pointer(ptr)))
} else { } else {
return (*string)(unsafe.Pointer(ptr)), nil 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(t)
default:
panic("internal error - argument type unrecognized")
} }
} }
func (interp *Interp) eval_arg_literally(p *process_t, pos int) (*string, error) { func (interp *Interp) eval_arg_literally(p *process_t, pos int) (Value_t, error) {
var ( /*
ptr uintptr var (
//cnode *Cnode_t ptr uintptr
) //cnode *Cnode_t
)
ptr = uintptr(p.GetArg(pos)) ptr = uintptr(p.GetArg(pos))
if ptr&1 == 1 { // cnode if ptr&1 == 1 { // cnode
ptr &= ^uintptr(1) ptr &= ^uintptr(1)
//cnode = (*Cnode_t)(unsafe.Pointer(ptr)) //cnode = (*Cnode_t)(unsafe.Pointer(ptr))
//cnode.child i hate this portion.... //cnode.child i hate this portion....
return nil, fmt.Errorf("not supported - unable to evaluate {} literally")
} else {
return (*string)(unsafe.Pointer(ptr)), nil
}*/
switch t := p.GetArg(pos).(type) {
case *string:
return t, nil
case *Cnode_t:
// TODO: can support this? by storing the original text?
return nil, fmt.Errorf("not supported - unable to evaluate {} literally") return nil, fmt.Errorf("not supported - unable to evaluate {} literally")
} else { default:
return (*string)(unsafe.Pointer(ptr)), nil panic("internal error - argument type unrecognized")
} }
} }
func (interp *Interp) EvalText(text []rune) (*string, error) { func (interp *Interp) EvalText(text []rune) (Value_t, error) {
var ( var (
v *string v Value_t
node *Cnode_t node *Cnode_t
err error err error
) )

View File

@ -3,7 +3,6 @@ package interp
import ( import (
"fmt" "fmt"
"runtime" "runtime"
"unsafe"
) )
type error_t struct { type error_t struct {
@ -40,9 +39,11 @@ type context_t struct {
container_node *Cnode_t container_node *Cnode_t
} }
type Value_t interface{}
type process_t struct { type process_t struct {
interp *Interp interp *Interp
vstack [16]unsafe.Pointer // value stack - TODO: change size vstack [16]Value_t // value stack - TODO: change size
vsp int vsp int
ctx *context_t ctx *context_t
} }
@ -227,11 +228,11 @@ func get_top_call_frame(f *CallFrame) *CallFrame {
} }
*/ */
func (interp *Interp) Execute(node_head *Cnode_t) (*string, error) { func (interp *Interp) Execute(node_head *Cnode_t) (Value_t, error) {
var ( var (
node *Cnode_t node *Cnode_t
v *string v Value_t
err error err error
) )

View File

@ -9,7 +9,9 @@ func proc_expr(p *process_t) error {
func proc_if(p *process_t) error { func proc_if(p *process_t) error {
var ( var (
v *string v Value_t
vv *string
ok bool
err error err error
) )
@ -24,14 +26,18 @@ func proc_if(p *process_t) error {
goto done goto done
} }
if *v != "" { vv, ok = v.(*string)
if !ok {
panic("internal error - screwed conditional value")
}
if *vv != "" {
//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 {
goto done goto done
} }
p.Return(*v) p.Return(v)
} else { } else {
// TODO: if elseif else // TODO: if elseif else
} }
@ -44,7 +50,8 @@ func proc_puts(p *process_t) error {
var ( var (
i int i int
nargs int nargs int
v *string v Value_t
vv *string
err error err error
) )
@ -59,11 +66,13 @@ func proc_puts(p *process_t) error {
if err != nil { if err != nil {
return err return err
} }
fmt.Printf("%s", *v)
vv, _ = v.(*string)
fmt.Printf("%s", *vv)
} }
if nargs >= 1 { if nargs >= 1 {
p.Return(*v) p.Return(v)
} else { } else {
p.Return("hello") p.Return("hello")
} }