diff --git a/env/env.go b/env/env.go index d6906f5f..51e8914b 100755 --- a/env/env.go +++ b/env/env.go @@ -2,7 +2,6 @@ package env import ( "fmt" - "reflect" "sort" "strings" "sync" @@ -15,12 +14,6 @@ import ( Set(word int, val Object) Object } */ -// UTIL - -func IsPointer(v interface{}) bool { - return reflect.TypeOf(v).Kind() == reflect.Ptr -} - // This is experimental env without map for Functions with up to two variables type EnvR2 struct { @@ -339,7 +332,7 @@ func NewProgramState(ser TSeries, idx *Idxs) *ProgramState { "", "", false, - NewLiveEnv(), + nil, // NewLiveEnv(), Rye2Dialect, NewEyrStack(), } diff --git a/env/envutil.go b/env/envutil.go index 0bb7e7e6..577c3d88 100644 --- a/env/envutil.go +++ b/env/envutil.go @@ -2,6 +2,7 @@ package env import ( "fmt" + "reflect" "time" ) @@ -39,3 +40,22 @@ func ToRyeValue(val any) Object { return Void{} } } + +func IsPointer(x any) bool { + return reflect.TypeOf(x).Kind() == reflect.Pointer +} + +func IsPointer2(x reflect.Value) bool { + return x.Kind() == reflect.Ptr +} + +func DereferenceAny(x any) any { + if reflect.TypeOf(x).Kind() == reflect.Ptr { + return reflect.ValueOf(x).Elem().Interface() + } + return x +} + +func ReferenceAny(x any) any { + return &x +} diff --git a/env/spreadsheet.go b/env/spreadsheet.go index 1eb7e6d9..9d361fe8 100644 --- a/env/spreadsheet.go +++ b/env/spreadsheet.go @@ -322,7 +322,11 @@ func (s SpreadsheetRow) GetKind() int { // Inspect returns a string func (s SpreadsheetRow) Inspect(e Idxs) string { - return "[SpreadsheetRow(" + strconv.Itoa(len(s.Values)) + ")" + "]" + p := "" + if IsPointer(s) { + p = "REF:" + } + return "[" + p + "SpreadsheetRow(" + strconv.Itoa(len(s.Values)) + ")" + "]" } // Inspect returns a string representation of the Integer. diff --git a/evaldo/builtins.go b/evaldo/builtins.go index 55f3faa5..58f98822 100644 --- a/evaldo/builtins.go +++ b/evaldo/builtins.go @@ -835,6 +835,33 @@ var builtins = map[string]*env.Builtin{ return &sp case env.Block: return &sp + case env.Native: + return &sp + default: + return MakeArgError(ps, 1, []env.Type{env.SpreadsheetType}, "thaw") + } + }, + }, + + "ref": { // temp duplicate + Argsn: 1, + Doc: "Makes a value (currently only spreadsheets) mutable instead of immutable", + Pure: true, + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch sp := arg0.(type) { + case env.Spreadsheet: + return &sp + case *env.Spreadsheet: + return sp + case env.Dict: + return &sp + case env.List: + return &sp + case env.Block: + return &sp + case env.Native: + sp.Value = env.ReferenceAny(sp.Value) + return &sp default: return MakeArgError(ps, 1, []env.Type{env.SpreadsheetType}, "thaw") } @@ -863,6 +890,31 @@ var builtins = map[string]*env.Builtin{ }, }, + "deref": { // TEMP duplicate + Argsn: 1, + Doc: "Makes a value (currently only spreadsheets) again immutable", + Pure: true, + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch sp := arg0.(type) { + case env.Spreadsheet: + return sp + case *env.Spreadsheet: + return *sp + case *env.Dict: + return *sp + case *env.List: + return *sp + case *env.Block: + return *sp + case *env.Native: + sp.Value = env.DereferenceAny(sp.Value) + return *sp + default: + return MakeArgError(ps, 1, []env.Type{env.SpreadsheetType}, "thaw") + } + }, + }, + "get_": { // *** find a name or decide on order of naming with generic words clashes with Argsn: 1, Doc: "Returns value of the word in context", @@ -1698,7 +1750,11 @@ var builtins = map[string]*env.Builtin{ Argsn: 1, Doc: "Prints information about a value.", Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { - fmt.Println(arg0.Inspect(*ps.Idx)) + p := "" + if env.IsPointer(arg0) { + p = "REF:" + } + fmt.Println(p + arg0.Inspect(*ps.Idx)) return arg0 }, }, @@ -1709,6 +1765,19 @@ var builtins = map[string]*env.Builtin{ return *env.NewString(arg0.Inspect(*ps.Idx)) }, }, + "is-ref": { // ** + Argsn: 1, + Doc: "Prints information about a value.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + // fmt.Println(arg0.Inspect(*ps.Idx)) + if env.IsPointer(arg0) { + return env.NewInteger(1) + } else { + return env.NewInteger(0) + } + }, + }, + "esc": { Argsn: 1, Doc: "Creates an escape sequence \033{}", diff --git a/evaldo/repl.go b/evaldo/repl.go index 2f2f4294..2c953580 100644 --- a/evaldo/repl.go +++ b/evaldo/repl.go @@ -240,11 +240,15 @@ func (r *Repl) evalLine(es *env.ProgramState, code string) string { if !es.ErrorFlag && es.Res != nil { r.prevResult = es.Res + p := "" + if env.IsPointer(es.Res) { + p = "Ref" + } resultStr := es.Res.Inspect(*genv) if r.dialect == "eyr" { resultStr = strings.Replace(resultStr, "Block:", "Stack:", 1) // TODO --- temp / hackish way ... make stack display itself or another approach } - output = fmt.Sprintf("\033[38;5;37m" + resultStr + "\x1b[0m") + output = fmt.Sprintf("\033[38;5;37m" + p + resultStr + "\x1b[0m") } es.ReturnFlag = false diff --git a/tests/main.rye b/tests/main.rye index 426e096e..be5f5f9f 100644 --- a/tests/main.rye +++ b/tests/main.rye @@ -2,7 +2,7 @@ ; Run test cases: ../rye main.rye test ; Generate documentation: ../rye main.rye doc > builtins.html -rye .args\raw :arg +rye .args\raw |load :args root-ctx: current-ctx test-framework: context { @@ -85,14 +85,19 @@ generate-doc-file: fn { filename menu } { menu: { "basics" "structures" "validation" "misc" "spreadsheet_mutations" } -switch arg { - "test" { +switch first args { + test { errors: 0 - for menu { + ".rye" |to-file |probe |probe |load |do\in* test-framework |+ errors ::errors } - print "===============" - print "FAILED TESTS: " + errors + either args .length? = 1 { + for menu { + ".rye" |to-file |load |do\in* test-framework |+ errors ::errors } + } { + + args .second + ".rye" |to-file |load |do\in* test-framework |+ errors ::errors + } + print "===================" + print " FAILED TESTS: " + errors } - "doc" { + doc { for menu { .generate-doc-file menu } } _ { print "use test or doc command" }