diff --git a/bin/main.go b/bin/main.go index 007100b..24984ca 100644 --- a/bin/main.go +++ b/bin/main.go @@ -76,34 +76,6 @@ func main() { } fmt.Printf("RETURN VALUE = [%s]\n", *v.(*string)) - /* - err = interp.FeedRunes([]rune(` - proc inc{x} { - puts {10 20} - return [expr $x + 1] - } - \{abc 11 2\ \1011 \ 2\x65 \uBc29\uaD6cdefg\uZZ\xZZ\U0000BC29\UAD6cZZ \ - [donkey 1 [expr [expr 2 + 3] + 3] ] - hello { world { }man} - "command { l a n g }" - set a [puts "1111" "22 22" "3333 [expr "123" + 2] 4444"] - abc [expr [expr 2 + "4[expr 2 * 6]"] + 9] - puts $a ${ kkk qqq } - puts "\x65\ubc29\n" - {}`)) - */ - //err = interp.FeedRunes([]rune(`hello [world [1 9] 2] - //`)) - /* - if err != nil { - fmt.Printf("ERROR %s\n", err) - } else { - err = interp.EndFeed() - if err != nil { - fmt.Printf("ERROR %s\n", err) - } - }*/ - interp.Close() f.Close() os.Exit(0) diff --git a/interp/eval.go b/interp/eval.go index 749e6e4..707a553 100644 --- a/interp/eval.go +++ b/interp/eval.go @@ -7,6 +7,7 @@ import ( var debug bool = false var err_num_args *error_t = &error_t{msg: "wrong number of arguments"} +var empty_string = "" /* value stack (p.vstack) @@ -20,6 +21,27 @@ var err_num_args *error_t = &error_t{msg: "wrong number of arguments"} evaluation stack (p.ctx) */ +func (p *process_t) push_call_frame() { + var cf *call_frame_t + + cf = &call_frame_t{} + if p.cframe == nil { + // let it point to the global frame located in the interp struct + cf.parent = p.interp.cframe + } else { + cf.parent = p.cframe + } + p.cframe = cf +} + +func (p *process_t) pop_call_frame() { + if p.cframe == p.interp.cframe { + p.cframe = nil + } else { + p.cframe = p.cframe.parent + } +} + func (p *process_t) push_cnode_value(val *Cnode_t) error { if p.vsp >= cap(p.vstack) { return fmt.Errorf("stack full") @@ -48,13 +70,25 @@ 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 if p.vsp < 2 { return fmt.Errorf("stack corrupt") } - v1, _ = p.vstack[p.vsp-2].(*string) - v2, _ = p.vstack[p.vsp-1].(*string) + v1, ok1 = p.vstack[p.vsp-2].(*string) + v2, ok2 = p.vstack[p.vsp-1].(*string) + + 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 !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-- @@ -90,6 +124,10 @@ func (p *process_t) call() error { // TODO: use a map switch *callee { + case "proc": + proc = proc_proc + case "set": + proc = proc_set case "if": proc = proc_if case "puts": @@ -216,9 +254,8 @@ puts "hello" world [STMT] [TEXT|null] [TEXT|1] */ -func (interp *Interp) eval_stmt_nodes(container_node *Cnode_t) (Value_t, error) { +func (interp *Interp) eval_stmt_nodes(p *process_t, container_node *Cnode_t) (Value_t, error) { var ( - p process_t v Value_t stmt_node *Cnode_t upper_node *Cnode_t @@ -230,7 +267,6 @@ func (interp *Interp) eval_stmt_nodes(container_node *Cnode_t) (Value_t, error) v = new(string) // TODO: change new(string) to a const - p.interp = interp upper_node = container_node stmt_node = upper_node.child // the first statement @@ -310,7 +346,7 @@ func (interp *Interp) eval_stmt_nodes(container_node *Cnode_t) (Value_t, error) } if debug { - 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) if p.ctx.container_node.code == CNODE_INIT || p.ctx.container_node.code == CNODE_BRACKET || p.ctx.container_node.code == CNODE_BRACE { @@ -363,21 +399,21 @@ func (interp *Interp) eval_stmt_nodes(container_node *Cnode_t) (Value_t, error) v = p.pop_value() // get the return value of the statement. if debug { - interp.dump_vstack(&p) + interp.dump_vstack(p) } break } v = p.pop_value() // get the return value of the statement. if debug { - interp.dump_vstack(&p) + interp.dump_vstack(p) } } done: if debug { - interp.dump_vstack(&p) + interp.dump_vstack(p) fmt.Printf("END p.sp = %d\n", p.vsp) } if p.vsp != org_vsp { @@ -410,7 +446,7 @@ func (interp *Interp) eval_arg(p *process_t, pos int) (Value_t, error) { case *string: return t, nil case *Cnode_t: - return interp.eval_stmt_nodes(t) + return interp.eval_stmt_nodes(p, t) default: panic("internal error - argument type unrecognized") } @@ -444,6 +480,12 @@ func (interp *Interp) eval_arg_literally(p *process_t, pos int) (Value_t, error) } } +func (interp *Interp) set_var(p *process_t, name Value_t, val Value_t) error { + //var err error_t + + return nil +} + func (interp *Interp) EvalText(text []rune) (Value_t, error) { var ( v Value_t diff --git a/interp/pcl.go b/interp/pcl.go index 72b205a..523a887 100644 --- a/interp/pcl.go +++ b/interp/pcl.go @@ -46,6 +46,7 @@ type process_t struct { vstack [16]Value_t // value stack - TODO: change size vsp int ctx *context_t + cframe *call_frame_t } type call_frame_t struct { @@ -107,7 +108,6 @@ type Cnode_t struct { next *Cnode_t child *Cnode_t // for container nodes code cnode_code_t - seqno int token []rune } @@ -116,9 +116,9 @@ type Interp struct { level int max_level int - feed *feed_struct_t - call_frame *call_frame_t - result string + feed *feed_struct_t + cframe *call_frame_t + result string } func NewInterp(max_level int, strict bool) (*Interp, error) { @@ -139,10 +139,15 @@ func NewInterp(max_level int, strict bool) (*Interp, error) { interp.push_feed_struct(FEED_TOP) interp.push_feed_struct(FEED_INIT) + // global cframe? + interp.cframe = &call_frame_t{} + return interp, nil } func (interp *Interp) Close() { + interp.cframe = nil + for interp.feed != nil { interp.pop_feed_struct() } @@ -234,8 +239,11 @@ func (interp *Interp) Execute(node_head *Cnode_t) (Value_t, error) { node *Cnode_t v Value_t err error + p process_t ) + p = process_t{interp: interp, vsp: 0} + v = new(string) // if there is no code the execute, the return value is an empty string for node = node_head; node != nil; node = node.next { @@ -248,7 +256,7 @@ 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(node) + v, err = interp.eval_stmt_nodes(&p, node) if err != nil { return nil, err } diff --git a/interp/proc.go b/interp/proc.go index 5116091..de625ce 100644 --- a/interp/proc.go +++ b/interp/proc.go @@ -2,6 +2,65 @@ package interp import "fmt" +func proc_proc(p *process_t) error { + /* + p.push_call_frame() + p.set_var("aaa", 10) + p.set_var("bbb", 20) + p.eval_stmt_nodes() + p.pop_call_frame() + */ + var err error + + if p.GetNumArgs() != 3 { + err = err_num_args + goto done + } + + /* + // procedure name + v1, err = p.interp.eval_arg(p, 0) + if err != nil { + goto done + } + + p.set_var(p, v1, v2)*/ +done: + return err +} + +func proc_set(p *process_t) error { + var ( + v1, v2 Value_t + err error + ) + + if p.GetNumArgs() != 2 { + err = err_num_args + goto done + } + + v1, err = p.interp.eval_arg(p, 0) + if err != nil { + goto done + } + + v2, err = p.interp.eval_arg(p, 1) + if err != nil { + goto done + } + + err = p.interp.set_var(p, v1, v2) + if err != nil { + goto done + } + + p.Return(v2) + +done: + return err +} + func proc_expr(p *process_t) error { return nil