public Value Evaluate(Environment environment) { var value = expression.Evaluate(environment); value.info = info; if (value.IsList() || value.IsSet()) { var list = value.AsList().GetValue(); Value result = ValueNull.NULL; for (var i = 0; i < identifiers.Count; i++) { if (i < list.Count) { environment.Put(identifiers[i], list[i]); if (list[i].IsFunc() && typeof(FuncLambda) == value.GetType()) { ((FuncLambda)value).SetName(identifiers[i]); } result = list[i]; } else { environment.Put(identifiers[i], ValueNull.NULL); result = ValueNull.NULL; } } return(result); } throw new ControlErrorException(new ValueString("ERROR"), "Destructuring def expected list or set but got " + value.Type(), pos); }
public Interpreter(bool secure = true, bool legacy = true) { baseEnvironment = Environment.GetBaseEnvironment(secure, legacy); environment = baseEnvironment.NewEnv(); baseEnvironment.Put("stdout", new ValueOutput(new StringWriter())); baseEnvironment.Put("stdin", new ValueInput(new StringReader(""))); if (!secure) { baseEnvironment.Put("run", new FuncRun(this)); } }
private static void BindNativeFunc(Environment env, FuncBase func, string alias) { if (env.GetBase().Get("checkerlang_secure_mode", SourcePos.Unknown).AsBoolean().GetValue() && !func.IsSecure()) { return; } env.Put(func.GetName(), func); if (alias != null) { env.Put(alias, func); } }
private void Verify(string expected, string script, string variable, object value) { var env = new Environment(); env.Put(variable, value); var result = new Interpreter().Interpret(script, "{test}", env); Assert.AreEqual(expected, result.ToString()); }
public Value Evaluate(Environment environment) { var value = expression.Evaluate(environment); value.info = info; environment.Put(identifier, value); if (value.IsFunc() && typeof(FuncLambda) == value.GetType()) { ((FuncLambda)value).SetName(identifier); } return(value); }
public Value Evaluate(Environment environment) { var result = new ValueObject(); foreach (var member in members) { NodeDef def = (NodeDef)member; result.AddItem(def.GetIdentifier(), def.Evaluate(environment)); } environment.Put(identifier, result); return(result); }
public Value Evaluate(Environment environment) { var modules = environment.GetModules(); // resolve module file, identifier and name string spec; if (modulespec is NodeIdentifier) { spec = ((NodeIdentifier)this.modulespec).GetValue(); if (environment.IsDefined(spec)) { var val = environment.Get(spec, this.pos); if (!(val.IsObject() && val.AsObject().isModule)) { if (!val.IsString()) { throw new ControlErrorException(new ValueString("ERROR"), "Expected string or identifier modulespec but got " + val.Type(), pos); } spec = val.AsString().GetValue(); } } } else { var specval = this.modulespec.Evaluate(environment); if (!specval.IsString()) { throw new ControlErrorException(new ValueString("ERROR"), "Expected string or identifier modulespec but got " + specval.Type(), pos); } spec = specval.AsString().GetValue(); } var modulefile = spec; if (!modulefile.EndsWith(".ckl")) { modulefile += ".ckl"; } string moduleidentifier; var modulename = this.name; var parts = spec.Split('/'); var name = parts[parts.Length - 1]; if (name.EndsWith(".ckl")) { name = name.Substring(0, name.Length - 4); } moduleidentifier = name; if (modulename == null) { modulename = name; } environment.PushModuleStack(moduleidentifier, pos); // lookup or read module Environment moduleEnv = null; if (modules.ContainsKey(moduleidentifier)) { moduleEnv = modules[moduleidentifier]; } else { moduleEnv = environment.GetBase().NewEnv(); var modulesrc = ModuleLoader.LoadModule(modulefile, environment, pos); Node node = null; try { node = Parser.Parse(modulesrc, modulefile); } catch (Exception) { throw new ControlErrorException(new ValueString("ERROR"), "Cannot parse module " + moduleidentifier, pos); } node.Evaluate(moduleEnv); modules[moduleidentifier] = moduleEnv; } environment.PopModuleStack(); // bind module or contents of module if (unqualified) { foreach (var symbol in moduleEnv.GetLocalSymbols()) { if (symbol.StartsWith("_")) { continue; // skip private module symbols } environment.Put(symbol, moduleEnv.Get(symbol, pos)); } } else if (symbols != null) { foreach (var symbol in moduleEnv.GetLocalSymbols()) { if (symbol.StartsWith("_")) { continue; // skip private module symbols } if (!symbols.ContainsKey(symbol)) { continue; } environment.Put(symbols[symbol], moduleEnv.Get(symbol, pos)); } } else { var obj = new ValueObject { isModule = true }; foreach (var symbol in moduleEnv.GetLocalSymbols()) { if (symbol.StartsWith("_")) { continue; // skip private module symbols } var val = moduleEnv.Get(symbol, pos); if (val.IsObject() && val.AsObject().isModule) { continue; // do not re-export modules! } obj.AddItem(symbol, val); } environment.Put(modulename, obj); } return(ValueNull.NULL); }
public void SetStandardOutput(TextWriter stdout) { baseEnvironment.Put("stdout", new ValueOutput(stdout)); }
public static void Bind(Environment env, string nativeName, string nativeAlias, SourcePos pos) { switch (nativeName) { case "acos": BindNativeFunc(env, new FuncAcos(), nativeAlias); break; case "add": BindNativeFunc(env, new FuncAdd(), nativeAlias); break; case "append": BindNativeFunc(env, new FuncAppend(), nativeAlias); break; case "asin": BindNativeFunc(env, new FuncAsin(), nativeAlias); break; case "atan": BindNativeFunc(env, new FuncAtan(), nativeAlias); break; case "atan2": BindNativeFunc(env, new FuncAtan2(), nativeAlias); break; case "bind_native": BindNativeFunc(env, new FuncBindNative(), nativeAlias); break; case "body": BindNativeFunc(env, new FuncBody(), nativeAlias); break; case "boolean": BindNativeFunc(env, new FuncBoolean(), nativeAlias); break; case "ceiling": BindNativeFunc(env, new FuncCeiling(), nativeAlias); break; case "close": BindNativeFunc(env, new FuncClose(), nativeAlias); break; case "compare": BindNativeFunc(env, new FuncCompare(), nativeAlias); break; case "contains": BindNativeFunc(env, new FuncContains(), nativeAlias); break; case "cos": BindNativeFunc(env, new FuncCos(), nativeAlias); break; case "date": BindNativeFunc(env, new FuncDate(), nativeAlias); break; case "decimal": BindNativeFunc(env, new FuncDecimal(), nativeAlias); break; case "delete_at": BindNativeFunc(env, new FuncDeleteAt(), nativeAlias); break; case "div": BindNativeFunc(env, new FuncDiv(), nativeAlias); break; case "ends_with": BindNativeFunc(env, new FuncEndsWith(), nativeAlias); break; case "equals": BindNativeFunc(env, new FuncEquals(), nativeAlias); break; case "escape_pattern": BindNativeFunc(env, new FuncEscapePattern(), nativeAlias); break; case "eval": BindNativeFunc(env, new FuncEval(), nativeAlias); break; case "execute": BindNativeFunc(env, new FuncExecute(), nativeAlias); break; case "exp": BindNativeFunc(env, new FuncExp(), nativeAlias); break; case "file_copy": BindNativeFunc(env, new FuncFileCopy(), nativeAlias); break; case "file_delete": BindNativeFunc(env, new FuncFileDelete(), nativeAlias); break; case "file_exists": BindNativeFunc(env, new FuncFileExists(), nativeAlias); break; case "file_info": BindNativeFunc(env, new FuncFileInfo(), nativeAlias); break; case "file_input": BindNativeFunc(env, new FuncFileInput(), nativeAlias); break; case "file_move": BindNativeFunc(env, new FuncFileMove(), nativeAlias); break; case "file_output": BindNativeFunc(env, new FuncFileOutput(), nativeAlias); break; case "find": BindNativeFunc(env, new FuncFind(), nativeAlias); break; case "find_last": BindNativeFunc(env, new FuncFindLast(), nativeAlias); break; case "floor": BindNativeFunc(env, new FuncFloor(), nativeAlias); break; case "format_date": BindNativeFunc(env, new FuncFormatDate(), nativeAlias); break; case "get_env": BindNativeFunc(env, new FuncGetEnv(), nativeAlias); break; case "get_output_string": BindNativeFunc(env, new FuncGetOutputString(), nativeAlias); break; case "greater": BindNativeFunc(env, new FuncGreater(), nativeAlias); break; case "greater_equals": BindNativeFunc(env, new FuncGreaterEquals(), nativeAlias); break; case "identity": BindNativeFunc(env, new FuncIdentity(), nativeAlias); break; case "if_empty": BindNativeFunc(env, new FuncIfEmpty(), nativeAlias); break; case "if_null": BindNativeFunc(env, new FuncIfNull(), nativeAlias); break; case "if_null_or_empty": BindNativeFunc(env, new FuncIfNullOrEmpty(), nativeAlias); break; case "info": BindNativeFunc(env, new FuncInfo(), nativeAlias); break; case "insert_at": BindNativeFunc(env, new FuncInsertAt(), nativeAlias); break; case "int": BindNativeFunc(env, new FuncInt(), nativeAlias); break; case "is_empty": BindNativeFunc(env, new FuncIsEmpty(), nativeAlias); break; case "is_not_empty": BindNativeFunc(env, new FuncIsNotEmpty(), nativeAlias); break; case "is_not_null": BindNativeFunc(env, new FuncIsNotNull(), nativeAlias); break; case "is_null": BindNativeFunc(env, new FuncIsNull(), nativeAlias); break; case "length": BindNativeFunc(env, new FuncLength(), nativeAlias); break; case "less": BindNativeFunc(env, new FuncLess(), nativeAlias); break; case "less_equals": BindNativeFunc(env, new FuncLessEquals(), nativeAlias); break; case "list": BindNativeFunc(env, new FuncList(), nativeAlias); break; case "list_dir": BindNativeFunc(env, new FuncListDir(), nativeAlias); break; case "log": BindNativeFunc(env, new FuncLog(), nativeAlias); break; case "lower": BindNativeFunc(env, new FuncLower(), nativeAlias); break; case "ls": BindNativeFunc(env, new FuncLs(), nativeAlias); break; case "make_dir": BindNativeFunc(env, new FuncMakeDir(), nativeAlias); break; case "map": BindNativeFunc(env, new FuncMap(), nativeAlias); break; case "matches": BindNativeFunc(env, new FuncMatches(), nativeAlias); break; case "mod": BindNativeFunc(env, new FuncMod(), nativeAlias); break; case "mul": BindNativeFunc(env, new FuncMul(), nativeAlias); break; case "not_equals": BindNativeFunc(env, new FuncNotEquals(), nativeAlias); break; case "object": BindNativeFunc(env, new FuncObject(), nativeAlias); break; case "parse": BindNativeFunc(env, new FuncParse(), nativeAlias); break; case "parse_date": BindNativeFunc(env, new FuncParseDate(), nativeAlias); break; case "parse_json": BindNativeFunc(env, new FuncParseJson(), nativeAlias); break; case "pattern": BindNativeFunc(env, new FuncPattern(), nativeAlias); break; case "pow": BindNativeFunc(env, new FuncPow(), nativeAlias); break; case "print": BindNativeFunc(env, new FuncPrint(), nativeAlias); break; case "println": BindNativeFunc(env, new FuncPrintln(), nativeAlias); break; case "process_lines": BindNativeFunc(env, new FuncProcessLines(), nativeAlias); break; case "put": BindNativeFunc(env, new FuncPut(), nativeAlias); break; case "random": BindNativeFunc(env, new FuncRandom(), nativeAlias); break; case "range": BindNativeFunc(env, new FuncRange(), nativeAlias); break; case "read": BindNativeFunc(env, new FuncRead(), nativeAlias); break; case "read_all": BindNativeFunc(env, new FuncReadall(), nativeAlias); break; case "readln": BindNativeFunc(env, new FuncReadln(), nativeAlias); break; case "remove": BindNativeFunc(env, new FuncRemove(), nativeAlias); break; case "replace": BindNativeFunc(env, new FuncReplace(), nativeAlias); break; case "round": BindNativeFunc(env, new FuncRound(), nativeAlias); break; case "s": BindNativeFunc(env, new FuncS(), nativeAlias); break; case "set": BindNativeFunc(env, new FuncSet(), nativeAlias); break; case "set_seed": BindNativeFunc(env, new FuncSetSeed(), nativeAlias); break; case "sin": BindNativeFunc(env, new FuncSin(), nativeAlias); break; case "sorted": BindNativeFunc(env, new FuncSorted(), nativeAlias); break; case "split": BindNativeFunc(env, new FuncSplit(), nativeAlias); break; case "split2": BindNativeFunc(env, new FuncSplit2(), nativeAlias); break; case "sqrt": BindNativeFunc(env, new FuncSqrt(), nativeAlias); break; case "str_input": BindNativeFunc(env, new FuncStrInput(), nativeAlias); break; case "starts_with": BindNativeFunc(env, new FuncStartsWith(), nativeAlias); break; case "str_output": BindNativeFunc(env, new FuncStrOutput(), nativeAlias); break; case "string": BindNativeFunc(env, new FuncString(), nativeAlias); break; case "sub": BindNativeFunc(env, new FuncSub(), nativeAlias); break; case "sublist": BindNativeFunc(env, new FuncSublist(), nativeAlias); break; case "substr": BindNativeFunc(env, new FuncSubstr(), nativeAlias); break; case "sum": BindNativeFunc(env, new FuncSum(), nativeAlias); break; case "tan": BindNativeFunc(env, new FuncTan(), nativeAlias); break; case "timestamp": BindNativeFunc(env, new FuncTimestamp(), nativeAlias); break; case "trim": BindNativeFunc(env, new FuncTrim(), nativeAlias); break; case "type": BindNativeFunc(env, new FuncType(), nativeAlias); break; case "upper": BindNativeFunc(env, new FuncUpper(), nativeAlias); break; case "zip": BindNativeFunc(env, new FuncZip(), nativeAlias); break; case "zip_map": BindNativeFunc(env, new FuncZipMap(), nativeAlias); break; case "E": env.Put("E", new ValueDecimal((decimal)Math.E).WithInfo("E\n\nThe mathematical constant E (Eulers number)")); break; case "PI": env.Put("PI", new ValueDecimal((decimal)Math.PI).WithInfo("PI\n\nThe mathematical constant PI")); break; case "PS": env.Put("PS", new ValueString(Path.DirectorySeparatorChar.ToString()).WithInfo("PS\n\nThe OS path separator (posix: /, windows: \\).")); break; case "LS": env.Put("LS", new ValueString(System.Environment.NewLine).WithInfo("PS\n\nThe OS line separator (posix: \\n, windows: \\r\\n).")); break; case "FS": env.Put("FS", new ValueString(Path.PathSeparator.ToString()).WithInfo("FS\n\nThe OS field separator (posix: :, windows: ;).")); break; case "OS_NAME": env.Put("OS_NAME", new ValueString(GetOsName()).WithInfo("OS_NAME\n\nThe name of the operating system, one of Windows, Linux, macOS")); break; case "OS_VERSION": env.Put("OS_VERSION", new ValueString(GetOsVersion()).WithInfo("OS_VERSION\n\nThe version of the operating system.")); break; case "OS_ARCH": env.Put("OS_ARCH", new ValueString(GetOsArch()).WithInfo("OS_ARCH\n\nThe architecture of the operating system, one of x86, amd64.")); break; default: throw new ControlErrorException(new ValueString("ERROR"), "Unknown native " + nativeName, pos); } }
public Value Evaluate(Environment environment) { var list = expression.Evaluate(environment); if (list.IsInput()) { var input = list.AsInput(); Value result = ValueBoolean.TRUE; string line = null; try { line = input.ReadLine(); while (line != null) { var value = new ValueString(line); if (identifiers.Count == 1) { environment.Put(identifiers[0], value); } else { var vals = value.AsList().GetValue(); for (int i = 0; i < identifiers.Count; i++) { environment.Put(identifiers[i], vals[i]); } } result = block.Evaluate(environment); if (result.IsBreak()) { result = ValueBoolean.TRUE; break; } if (result.IsContinue()) { result = ValueBoolean.TRUE; // continue } if (result.IsReturn()) { break; } line = input.ReadLine(); } if (identifiers.Count == 1) { environment.Remove(identifiers[0]); } else { for (var i = 0; i < identifiers.Count; i++) { environment.Remove(identifiers[i]); } } } catch (IOException) { throw new ControlErrorException(new ValueString("ERROR"), "Cannot read from input", pos); } return(result); } if (list.IsList()) { Value result = ValueBoolean.TRUE; foreach (var value in list.AsList().GetValue()) { if (identifiers.Count == 1) { environment.Put(identifiers[0], value); } else { var vals = value.AsList().GetValue(); for (int i = 0; i < identifiers.Count; i++) { environment.Put(identifiers[i], vals[i]); } } result = block.Evaluate(environment); if (result.IsBreak()) { result = ValueBoolean.TRUE; break; } if (result.IsContinue()) { result = ValueBoolean.TRUE; // continue } if (result.IsReturn()) { break; } } if (identifiers.Count == 1) { environment.Remove(identifiers[0]); } else { for (var i = 0; i < identifiers.Count; i++) { environment.Remove(identifiers[i]); } } return(result); } if (list.IsSet()) { Value result = ValueBoolean.TRUE; foreach (var value in list.AsSet().GetValue()) { if (identifiers.Count == 1) { environment.Put(identifiers[0], value); } else { var vals = value.AsList().GetValue(); for (int i = 0; i < identifiers.Count; i++) { environment.Put(identifiers[i], vals[i]); } } result = block.Evaluate(environment); if (result.IsBreak()) { result = ValueBoolean.TRUE; break; } if (result.IsContinue()) { result = ValueBoolean.TRUE; // continue } if (result.IsReturn()) { break; } } if (identifiers.Count == 1) { environment.Remove(identifiers[0]); } else { for (var i = 0; i < identifiers.Count; i++) { environment.Remove(identifiers[i]); } } return(result); } if (list.IsMap()) { Value result = ValueBoolean.TRUE; if (what == "keys") { foreach (var val in list.AsMap().GetValue().Keys.ToList()) { if (identifiers.Count == 1) { environment.Put(identifiers[0], val); } else { var vals = val.AsList().GetValue(); for (int i = 0; i < identifiers.Count; i++) { environment.Put(identifiers[i], vals[i]); } } result = block.Evaluate(environment); if (result.IsBreak()) { result = ValueBoolean.TRUE; break; } if (result.IsContinue()) { result = ValueBoolean.TRUE; // continue } if (result.IsReturn()) { break; } } } else if (what == "values") { foreach (var val in list.AsMap().GetValue().Values.ToList()) { if (identifiers.Count == 1) { environment.Put(identifiers[0], val); } else { var vals = val.AsList().GetValue(); for (int i = 0; i < identifiers.Count; i++) { environment.Put(identifiers[i], vals[i]); } } result = block.Evaluate(environment); if (result.IsBreak()) { result = ValueBoolean.TRUE; break; } if (result.IsContinue()) { result = ValueBoolean.TRUE; // continue } if (result.IsReturn()) { break; } } } else if (what == "entries") { foreach (var entry in list.AsMap().GetValue().ToList()) { ValueList val = new ValueList(); val.AddItem(entry.Key); val.AddItem(entry.Value); if (identifiers.Count == 1) { environment.Put(identifiers[0], val); } else { var vals = val.AsList().GetValue(); for (int i = 0; i < identifiers.Count; i++) { environment.Put(identifiers[i], vals[i]); } } result = block.Evaluate(environment); if (result.IsBreak()) { result = ValueBoolean.TRUE; break; } if (result.IsContinue()) { result = ValueBoolean.TRUE; // continue } if (result.IsReturn()) { break; } } } if (identifiers.Count == 1) { environment.Remove(identifiers[0]); } else { for (var i = 0; i < identifiers.Count; i++) { environment.Remove(identifiers[i]); } } return(result); } if (list.IsObject()) { Value result = ValueBoolean.TRUE; if (what == "keys") { foreach (var key in list.AsObject().value.Keys.ToList()) { Value val = new ValueString(key); environment.Put(identifiers[0], val); result = block.Evaluate(environment); if (result.IsBreak()) { result = ValueBoolean.TRUE; break; } if (result.IsContinue()) { result = ValueBoolean.TRUE; // continue } if (result.IsReturn()) { break; } } } else if (what == "values") { foreach (var val in list.AsObject().value.Values.ToList()) { if (identifiers.Count == 1) { environment.Put(identifiers[0], val); } else { var vals = val.AsList().GetValue(); for (int i = 0; i < identifiers.Count; i++) { environment.Put(identifiers[i], vals[i]); } } result = block.Evaluate(environment); if (result.IsBreak()) { result = ValueBoolean.TRUE; break; } if (result.IsContinue()) { result = ValueBoolean.TRUE; // continue } if (result.IsReturn()) { break; } } } else if (what == "entries") { foreach (var entry in list.AsObject().value.ToList()) { var val = new ValueList(); val.AddItem(new ValueString(entry.Key)); val.AddItem(entry.Value); if (identifiers.Count == 1) { environment.Put(identifiers[0], val); } else { var vals = val.AsList().GetValue(); for (int i = 0; i < identifiers.Count; i++) { environment.Put(identifiers[i], vals[i]); } } result = block.Evaluate(environment); if (result.IsBreak()) { result = ValueBoolean.TRUE; break; } if (result.IsContinue()) { result = ValueBoolean.TRUE; // continue } if (result.IsReturn()) { break; } } } if (identifiers.Count == 1) { environment.Remove(identifiers[0]); } else { for (var i = 0; i < identifiers.Count; i++) { environment.Remove(identifiers[i]); } } return(result); } if (list.IsString()) { var str = list.AsString().GetValue(); Value result = ValueBoolean.TRUE; foreach (var value in str) { environment.Put(identifiers[0], new ValueString(value.ToString())); result = block.Evaluate(environment); if (result.IsBreak()) { result = ValueBoolean.TRUE; break; } if (result.IsContinue()) { result = ValueBoolean.TRUE; // continue } if (result.IsReturn()) { break; } } environment.Remove(identifiers[0]); return(result); } throw new ControlErrorException(new ValueString("ERROR"), "Cannot iterate over " + list, pos); }