public static SExp Eq(SExp[] vals, Environment env) { Utilities.CheckArguments(vals, args=>args.Length==2, "eq: "); SExp lhs = vals[0]; SExp rhs = vals[1]; return new Boolean(lhs == rhs); }
public static SExp Cons(SExp[] vals, Environment env) { Utilities.CheckArguments(vals, args=>args.Length==2, "cons: "); SExp car = vals[0]; SExp cdr = vals[1]; return new Cell(car, cdr); }
public static SExp Eval(SExp[] vals, Environment env) { Utilities.CheckArguments(vals, args=>args.Length==2, "eval: "); SExp body = vals[0]; Environment envGiven = Environment.FromSExpression(vals[1]); return Utilities.Eval(body, envGiven); }
public static SExp Cond(SExp[] vals, Environment env) { SExp res = new Undefined(); foreach (SExp exp in vals) { if (!(exp is Cell)) { string msg = "cond: malformed clauses."; throw new TypeNotMatchException(msg); } SExp test = (exp as Cell).Car; if (!((exp as Cell).Cdr is Cell)) { string msg = "cond: malformed clauses."; throw new TypeNotMatchException(msg); } SExp[] body = ((exp as Cell).Cdr as Cell).ToArray(); if (Utilities.CanRegardAsTrue(Utilities.Eval(test, env))) { res = Utilities.Eval(body, env); break; } } return res; }
public SExp ToSExp() { var list = SExp.List(SExp.List("success?", IsSuccess())); if (IsSuccess()) { list.Push( SExp.List("nodes", SExp.List(Nodes?.Select(n => n.ToSExp()).ToArray())), SExp.List("rest", Rest), SExp.List("message", Message), SExp.List("fail_rest", FailRest)); } else { list.Push( SExp.List("message", Message), SExp.List("fail_rest", FailRest), SExp.List("rest", Rest), SExp.List("nodes", SExp.List(Nodes?.Select(n => n.ToSExp()).ToArray()))); } if (!string.IsNullOrEmpty(ParserName)) { list.PushFront(SExp.List(SExp.List("parser", ParserName))); } return(list); }
public static SExp Cdr(SExp e) { Cons c = e as Cons; if (c == null) { return(null); } return(c.Cdr); }
public static SExp And(SExp[] vals, Environment env) { SExp res = new Boolean(true); foreach (SExp exp in vals) { res = Utilities.Eval(exp, env); if (!Utilities.CanRegardAsTrue(res)) return new Boolean(false); } return res; }
public static SExp Cdr(SExp[] vals, Environment env) { Utilities.CheckArguments(vals, args=>args.Length==1, "cdr: "); SExp cell = vals[0]; if (!(cell is Cell)) { string msg = "cdr: Parameter must be pair."; throw new TypeNotMatchException(msg); } return (cell as Cell).Cdr; }
public static SExp EqualNumbers(SExp[] vals, Environment env) { Utilities.CheckArguments(vals, args=>args.Length==2, "=: "); SExp lhs = vals[0]; SExp rhs = vals[1]; if (!(lhs is Integer) || !(rhs is Integer)) { string msg = "=: Parameters must be numeric value."; throw new TypeNotMatchException(msg); } return new Boolean(((int)(lhs as Integer).Value) == ((int)(rhs as Integer).Value)); }
public static Expression From(SExp exp) { if (exp is SExpAtom a) { return(From(a)); } if (exp is SExpList l) { return(From(l)); } throw new NotImplementedException(); }
public static SExp Add(SExp[] vals, Environment env) { int sum = 0; foreach (SExp exp in vals) { if (!(exp is Integer)) { string msg = "+: Parameters must be numeric value."; throw new TypeNotMatchException(msg); } sum += ((int)(exp as Integer).Value); } return new Integer(sum); }
public ListSExp ToSExp() { if (!IsEmpty()) { var lst = SExp.List(SExp.List( SExp.List("parser", _parser.ToString()), SExp.List("toks", _toks.ToString()))); lst.Append(_prev.ToSExp()); return(lst); } else { return(SExp.List()); } }
public static SExp Define(SExp[] vals, Environment env) { Utilities.CheckArguments(vals, args=>args.Length==2, "define: "); SExp name = vals[0]; if (!(name is Identifier)) { string msg = "define: The first argument must be identifier."; throw new TypeNotMatchException(msg); } SExp exp = Utilities.Eval(vals[1], env); env.Add(new Entry((name as Identifier).Value as string, exp)); return name; }
public static SExp If(SExp[] vals, Environment env) { Utilities.CheckArguments(vals, args=>args.Length==3, "if: "); SExp test = vals[0]; SExp case1 = vals[1]; SExp case2 = vals[2]; SExp ret = null; if (Utilities.CanRegardAsTrue(Utilities.Eval(test, env))) { ret = Utilities.Eval(case1, env); } else { ret = Utilities.Eval(case2, env); } return ret; }
public SExp ToSExp() { if (IsLeaf()) { return(SExp.Value(Value)); } else if (TryGetStringValue(out var value)) { var lst = SExp.List(GetNodeMeta()); if (!string.IsNullOrEmpty(value)) { lst.Push(value); } return(lst); } else { var lst = SExp.List(Children.Select(n => n.ToSExp()).ToArray()); lst.PushFront(GetNodeMeta()); return(lst); } }
public static SExp Setq(SExp[] vals, Environment env) { Utilities.CheckArguments(vals, args=>args.Length==2, "set!: "); if (!(vals[0] is Identifier)) { string msg = "The first argument must be identifier."; throw new TypeNotMatchException(msg); } Identifier name = vals[0] as Identifier; SExp val = Utilities.Eval(vals[1], env); if (!env.Reassign(name.Value as string, val)) { string msg = string.Format("Identifier '{0}' is undefined.", name); throw new IdentifierNotDefinedException(msg); } return name; }
public static SExp Let(SExp[] vals, Environment env) { Utilities.CheckArguments(vals, args=>2<=args.Length, "let: "); EnvironmentFrame frame = null; try { frame = EnvironmentFrame.FromSExpression(vals[0]); foreach (Entry entry in frame) { entry.Rest = Utilities.Eval(entry.Rest, env); } } catch (TypeNotMatchException) { string msg = "let: malformed init list."; throw new TypeNotMatchException(msg); } SExp[] body = Enumerable.Skip(vals, 1).ToArray(); return Closure.Eval(env, frame, body); }
public static SExp Quote(SExp[] vals, Environment env) { Utilities.CheckArguments(vals, args=>args.Length==1, "quote: "); return vals[0]; }
public static SExp Exit(SExp[] vals, Environment env) { Utilities.CheckArguments(vals, args=>args.Length==0, "exit: "); string msg = "Scalop was terminated."; throw new ApplicationTerminationException(msg); }
public Cons(SExp Car, SExp Cdr) { this.Car = Car; this.Cdr = Cdr; }
public static SExp Input(SExp x) => x;
public static SExp Lambda(SExp[] vals, Environment env) { Utilities.CheckArguments(vals, args=>2<=args.Length, "lambda: "); SExp formal = vals[0]; if (formal is Atom) { if (formal is Identifier) { string msg = "lambda: Variable-length argument is not supported yet."; throw new NotSupportedYetException(msg); } else { string msg = "lambda: Formal parameter must be pair or identifier."; throw new TypeNotMatchException(msg); } } List<string> f = new List<string>(); for (SExp c = formal; c is Cell; c = (c as Cell).Cdr) { if (!((c as Cell).Car is Identifier)) { string msg = "lambda: All parameters must be identifier."; throw new TypeNotMatchException(msg); } f.Add(((c as Cell).Car as Identifier).Value as string); } return new Closure(f.ToArray(), Enumerable.Skip(vals,1).ToArray(), env); }
public static SExp InteractionEnvironment(SExp[] vals, Environment env) { Utilities.CheckArguments(vals, args=>args.Length==0, "interaction-environment: "); return env.ToSExpression(); }
public static SExp Select(SExp x) => x;
public static SExp Mul(SExp[] vals, Environment env) { int n = 1; foreach (SExp exp in vals) { if (!(exp is Integer)) { string msg = "*: Parameters must be numeric value."; throw new TypeNotMatchException(msg); } n *= ((int)(exp as Integer).Value); } return new Integer(n); }
public static SExp Not(SExp[] vals, Environment env) { Utilities.CheckArguments(vals, args=>args.Length==1, "not: "); SExp exp = vals[0]; return Utilities.CanRegardAsTrue(exp) ? Boolean.FALSE : Boolean.TRUE; }
public LexingResult(SExp result) { this.result = result; }
static void Main(string[] args) { //LispTest.UnitTest(); bool needHelp = true; for (int i = 0; i < args.Length; ++i) { switch (args[i]) { case "-include": // 読み込むファイルが指定されている。 eval(args[i + 1], true); needHelp = false; ++i; break; case "-import": // 読み込むファイルが指定されている。 eval(args[i + 1], false); needHelp = false; ++i; break; case "-test": // UnitTest LispTest.UnitTest(); needHelp = false; break; // http://d.hatena.ne.jp/ak11/20091122 のpatch case "-compile": try { string filename = args[++i]; string output = args[++i]; // 出力ファイルよりソースファイルが新しい時のみ処理 if (!File.Exists(output) || File.GetLastWriteTime(output) < File.GetLastWriteTime(filename)) { Console.WriteLine(filename + " => " + output); var lisp = new Lisp(); lisp.setVar("outfile", new SExp { elms = output }); SExp ret = lisp.eval(new ConvSExp().import(filename)); // Console.WriteLine(lisp.SExp2string(ret)); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } needHelp = false; break; case "-help": case "-h": Help(); needHelp = false; break; } } if (needHelp) { Help(); } }
// Your semantics implementations here public static SExp Cons(SExp a, SExp d) => new Cons(a, d);
public static SExp Sub(SExp[] vals, Environment env) { if (vals.Length == 0) { string msg = "-: Procedure require at least one argument."; throw new ArityNotMatchException(msg); } else { SExp exp = vals[0]; if (!(exp is Integer)) { string msg = "-: Parameters must be numeric value."; throw new TypeNotMatchException(msg); } int n = (int)(exp as Integer).Value; if (vals.Length == 1) { n = -n; } else { for (int i = 1; i < vals.Length; i++) { if (!(vals[i] is Integer)) { string msg = "-: Parameters must be numeric value."; throw new TypeNotMatchException(msg); } n -= ((int)(vals[i] as Integer).Value); } } return new Integer(n); } }
public static SExp Null(SExp[] vals, Environment env) { Utilities.CheckArguments(vals, args=>args.Length==1, "null?: "); SExp exp = vals[0]; return exp is Nil ? Boolean.TRUE : Boolean.FALSE; }
public static SExp Atom(SExp[] vals, Environment env) { Utilities.CheckArguments(vals, args=>args.Length==1, "atom?: "); SExp exp = vals[0]; return new Boolean(exp is Atom); }
public ListSExp ToSExp() { return(SExp.List()); }