| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | package interp | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"unsafe" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | var debug bool = true | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | var err_num_args *error_t = &error_t{msg: "wrong number of arguments"} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	   value stack (p.vstack) | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 		           <--- SP (p.vsp) | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 		    ARG1 | 
					
						
							|  |  |  | 		    ARG0 | 
					
						
							|  |  |  | 		    NAME | 
					
						
							|  |  |  | 			RET | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		evaluation stack (p.ctx) | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (p *process_t) push_cnode_value(val *Cnode_t) error { | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	if p.vsp >= cap(p.vstack) { | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 		return fmt.Errorf("stack full") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	// TODO: using the last bit won't be compatible with go's GC. | 
					
						
							|  |  |  | 	// CHANGE to use inteface{} or devise a different scheme... | 
					
						
							|  |  |  | 	p.vstack[p.vsp] = unsafe.Pointer(uintptr(unsafe.Pointer(val)) | 1) | 
					
						
							|  |  |  | 	p.vsp++ | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 	p.ctx.count++ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (p *process_t) push_string_value(val string) error { | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	if p.vsp >= cap(p.vstack) { | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 		return fmt.Errorf("stack full") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	p.vstack[p.vsp] = unsafe.Pointer(&val) | 
					
						
							|  |  |  | 	p.vsp++ | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 	p.ctx.count++ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (p *process_t) merge_top_values() error { | 
					
						
							|  |  |  | 	var new_val string | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	if p.vsp < 2 { | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 		return fmt.Errorf("stack corrupt") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	new_val = *(*string)(p.vstack[p.vsp-2]) + *(*string)(p.vstack[p.vsp-1]) | 
					
						
							|  |  |  | 	p.vsp-- | 
					
						
							|  |  |  | 	p.vstack[p.vsp] = nil | 
					
						
							|  |  |  | 	p.vstack[p.vsp-1] = unsafe.Pointer(&new_val) | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 	p.ctx.count-- | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (p *process_t) pop_value() unsafe.Pointer { | 
					
						
							|  |  |  | 	var v unsafe.Pointer | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	p.vsp-- | 
					
						
							|  |  |  | 	v = p.vstack[p.vsp] | 
					
						
							|  |  |  | 	p.vstack[p.vsp] = nil | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 	return v | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (p *process_t) call() error { | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		proc   func(*process_t) error | 
					
						
							|  |  |  | 		callee *string | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	callee = p.GetCalleeName() | 
					
						
							|  |  |  | 	// TODO: use a map | 
					
						
							|  |  |  | 	switch *callee { | 
					
						
							|  |  |  | 	case "if": | 
					
						
							|  |  |  | 		proc = proc_if | 
					
						
							|  |  |  | 	case "puts": | 
					
						
							|  |  |  | 		proc = proc_puts | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	case "true": | 
					
						
							|  |  |  | 		proc = proc_true | 
					
						
							|  |  |  | 	case "false": | 
					
						
							|  |  |  | 		proc = proc_false | 
					
						
							|  |  |  | 	case "null": | 
					
						
							|  |  |  | 		proc = proc_null | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		proc = proc_unknown | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return proc(p) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (p *process_t) GetCalleeName() *string { | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	return (*string)(p.vstack[p.vsp-p.ctx.count+1]) | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (p *process_t) GetArg(idx int) unsafe.Pointer { | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	return (p.vstack[p.vsp-p.ctx.count+2+idx]) | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (p *process_t) GetNumArgs() int { | 
					
						
							|  |  |  | 	return p.ctx.count - 2 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (p *process_t) Return(val string) { | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	p.vstack[p.vsp-p.ctx.count] = unsafe.Pointer(&val) | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | func (p *process_t) push_context(node *Cnode_t, container_node *Cnode_t) { | 
					
						
							|  |  |  | 	p.ctx = &context_t{count: 0, parent_ctx: p.ctx, parent_node: node, container_node: container_node} | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | func (p *process_t) pop_context(clear_vstack bool) (*Cnode_t, *Cnode_t) { | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	var ( | 
					
						
							|  |  |  | 		i         int | 
					
						
							|  |  |  | 		node      *Cnode_t | 
					
						
							|  |  |  | 		container *Cnode_t | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	node = p.ctx.parent_node | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	container = p.ctx.container_node | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	if clear_vstack { | 
					
						
							|  |  |  | 		// 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 | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 		// pop off the cleaned arguments | 
					
						
							|  |  |  | 		p.vsp -= p.ctx.count - 1 // keep the return value in the stack | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 	p.ctx = p.ctx.parent_ctx | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if p.ctx != nil { | 
					
						
							|  |  |  | 		p.ctx.count++ // let the return value be the argument to the caller | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	return node, container | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | func (interp *Interp) dump_vstack(p *process_t) { | 
					
						
							|  |  |  | 	fmt.Printf("p.VSP => %d\n", p.vsp) | 
					
						
							|  |  |  | 	for i := 0; i < p.vsp; i++ { | 
					
						
							|  |  |  | 		x := uintptr(p.vstack[i]) | 
					
						
							|  |  |  | 		if x&1 == 0 { | 
					
						
							|  |  |  | 			// string value | 
					
						
							|  |  |  | 			fmt.Printf(" %d => [%s]\n", i, *(*string)(p.vstack[i])) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			// cnode value | 
					
						
							|  |  |  | 			fmt.Printf(" %d => cnode %p", i, p.vstack[i]) // TODO: strip 1 off | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | puts "hello" world | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 	[STMT] | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 		[TEXT|puts] [DQUOTE] [TEXT|world] | 
					
						
							|  |  |  | 	                     [TEXT|hello] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [puts 1 2; puts 1] 999 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	[STMT] | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 	    [BRACKET] [TEXT|999] | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 		   [STMT] | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 		      [TEXT|puts] [TEXT|1] [TEXT|2] | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 		   [STMT] | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 		      [TEXT|puts] [TEXT|1] | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | "pu[null 1]ts" 10 20 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	[STMT] | 
					
						
							|  |  |  | 	     [DQUOTE] [TEXT|10] [TEXT|20] | 
					
						
							|  |  |  | 		    [TEXT|pu] [BRACKET] [JOIN] [TEXT|ts] [JOIN] | 
					
						
							|  |  |  | 			         [STMT] | 
					
						
							|  |  |  | 					    [TEXT|null] [TEXT|1] | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | func (interp *Interp) eval_stmt_nodes(container_node *Cnode_t) (*string, error) { | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 		p          process_t | 
					
						
							|  |  |  | 		v          *string | 
					
						
							|  |  |  | 		stmt_node  *Cnode_t | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 		upper_node *Cnode_t | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 		inner_node *Cnode_t | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 		is_stmt    bool | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 		err        error | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	v = new(string) // TODO: change new(string) to a const | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 	p.interp = interp | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 	upper_node = container_node | 
					
						
							|  |  |  | 	stmt_node = upper_node.child // the first statement | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	fmt.Printf("START p.sp = %d\n", p.vsp) | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 	for stmt_node != nil { | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 	start_over_0: | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 		if stmt_node.code != CNODE_STMT { | 
					
						
							|  |  |  | 			panic("internal error - not statement node") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 		//fmt.Printf("PUSHING CONTEXT.....\n") | 
					
						
							|  |  |  | 		p.push_context(stmt_node, upper_node) | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 		p.push_string_value("") // placeholder for return value | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 		//start_over: | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 		inner_node = stmt_node.child | 
					
						
							|  |  |  | 	resume: | 
					
						
							|  |  |  | 		for inner_node != nil { | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 			//fmt.Printf("handling %d\n", inner_node.code) | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 			switch inner_node.code { | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 			case CNODE_BRACKET: | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 				if inner_node.child != nil { | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 					upper_node = inner_node | 
					
						
							|  |  |  | 					stmt_node = upper_node.child | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 					if debug { | 
					
						
							|  |  |  | 						fmt.Printf("going to start over\n") | 
					
						
							|  |  |  | 						interp.dump_cnodes(stmt_node, true) | 
					
						
							|  |  |  | 						fmt.Printf("\n--\n") | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 					goto start_over_0 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 				} else { | 
					
						
							|  |  |  | 					// no statements inside []. treat it like an empty string | 
					
						
							|  |  |  | 					p.push_string_value("") | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 			case CNODE_DQUOTE: | 
					
						
							|  |  |  | 				if inner_node.child != nil { | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 					//fmt.Printf("PUSHING CONTEXT.....\n") | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 					p.push_context(stmt_node, inner_node) | 
					
						
							|  |  |  | 					//p.push_string_value("") // no placeholder for return value is needed | 
					
						
							|  |  |  | 					inner_node = inner_node.child | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 					if debug { | 
					
						
							|  |  |  | 						fmt.Printf("going to start over\n") | 
					
						
							|  |  |  | 						interp.dump_cnodes(stmt_node, true) | 
					
						
							|  |  |  | 						fmt.Printf("\n--\n") | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 					goto resume | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					// no statements inside []. treat it like an empty string | 
					
						
							|  |  |  | 					p.push_string_value("") | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 			case CNODE_BRACE: | 
					
						
							|  |  |  | 				p.push_cnode_value(inner_node) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 			case CNODE_TEXT: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 				//fmt.Printf("XXXXXXXXXXXXXXXXXXXx[%s]\n", string(inner_node.token)) | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 				err = p.push_string_value(string(inner_node.token)) | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					goto oops | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// TODO: many more types... | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 			case CNODE_JOIN: | 
					
						
							|  |  |  | 				p.merge_top_values() | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			inner_node = inner_node.next | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 		if debug { | 
					
						
							|  |  |  | 			interp.dump_vstack(&p) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 		//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 { | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 			if debug { | 
					
						
							|  |  |  | 				fmt.Printf("calling..... [%s]\n", *p.GetCalleeName()) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 			err = p.call() | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				goto oops | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 			is_stmt = true | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 			is_stmt = false | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 		//fmt.Printf("POPPING CONTEXT.....is_stmt[%v]\n", is_stmt) | 
					
						
							|  |  |  | 		stmt_node, upper_node = p.pop_context(is_stmt) | 
					
						
							|  |  |  | 		if upper_node != container_node { | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 			if debug { | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 				fmt.Printf("resuming... %d upper_node.next %p\n", p.vsp, upper_node.next) | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 			inner_node = upper_node.next // as if it hit the bottom of the innner for loop | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 			goto resume | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 		//fmt.Printf("POPPING VALUE...\n") | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 		v = (*string)(p.pop_value()) // get the return value of the statement. | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 		if debug { | 
					
						
							|  |  |  | 			interp.dump_vstack(&p) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 		stmt_node = stmt_node.next | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:43 +09:00
										 |  |  | 	if debug { | 
					
						
							|  |  |  | 		interp.dump_vstack(&p) | 
					
						
							|  |  |  | 		fmt.Printf("END p.sp = %d\n", p.vsp) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 	return v, nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | oops: | 
					
						
							|  |  |  | 	return nil, err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | func (interp *Interp) eval_arg(p *process_t, pos int) (*string, error) { | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		ptr uintptr | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ptr = uintptr(p.GetArg(pos)) | 
					
						
							|  |  |  | 	if ptr&1 == 1 { // cnode | 
					
						
							|  |  |  | 		ptr &= ^uintptr(1) | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 		//interp.dump_cnodes((*Cnode_t)(unsafe.Pointer(ptr)), true) | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 		//return interp.eval_atom_node((*Cnode_t)(unsafe.Pointer(ptr)).child) | 
					
						
							| 
									
										
										
										
											2023-08-03 22:34:42 +09:00
										 |  |  | 		return interp.eval_stmt_nodes((*Cnode_t)(unsafe.Pointer(ptr))) | 
					
						
							| 
									
										
										
										
											2023-07-21 18:32:51 +09:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		return (*string)(unsafe.Pointer(ptr)), nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (interp *Interp) eval_arg_literally(p *process_t, pos int) (*string, error) { | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		ptr uintptr | 
					
						
							|  |  |  | 		//cnode *Cnode_t | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ptr = uintptr(p.GetArg(pos)) | 
					
						
							|  |  |  | 	if ptr&1 == 1 { // cnode | 
					
						
							|  |  |  | 		ptr &= ^uintptr(1) | 
					
						
							|  |  |  | 		//cnode = (*Cnode_t)(unsafe.Pointer(ptr)) | 
					
						
							|  |  |  | 		//cnode.child i hate this portion.... | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("not supported - unable to evaluate {} literally") | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return (*string)(unsafe.Pointer(ptr)), nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (interp *Interp) EvalText(text []rune) (*string, error) { | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		v    *string | 
					
						
							|  |  |  | 		node *Cnode_t | 
					
						
							|  |  |  | 		err  error | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	interp.BeginFeed() // this resets the feed stack to the initial state | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = interp.FeedRunes(text) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		goto oops | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	node, err = interp.EndFeed() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		goto oops | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//fmt.Printf("--------------------\n") | 
					
						
							|  |  |  | 	//interp.dump_cnodes(node, true) | 
					
						
							|  |  |  | 	//fmt.Printf("--------------------\n") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	v, err = interp.Execute(node) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		goto oops | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return v, nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | oops: | 
					
						
							|  |  |  | 	return nil, err | 
					
						
							|  |  |  | } |