public static (Value, bool)? Apply(OsmiumEngine engine, ExpressionValue expr) { if (expr.Head is ExpressionValue hexpr) { if (hexpr.Head is Symbol sv && sv == engine.System.Apply && hexpr.Count == 1 && expr.Count == 1) { return(DoApply(engine, hexpr[0], expr[0], 0, 0), true); } } else if (expr.Head is Symbol sv && sv == engine.System.Apply) { if (expr.Count == 1) { return(null); } if (expr.Count == 2) { return(DoApply(engine, expr[0], expr[1], 0, 0), true); } // TODO levelspec } return(null); }
public static (Value, bool)? Append(OsmiumEngine engine, ExpressionValue expr) { if (!expr.Head.Equals(engine.System.Append)) { return(null); } if (expr.Count != 2) { // TODO: message return(null); } var list = expr[0]; var toAppend = expr[1]; if (list is ExpressionValue e) { var newParts = new Value[e.Count + 1]; Array.Copy(e.Parts.ToArray(), newParts, e.Count); newParts[e.Count] = toAppend; return(engine.Expr(e.Head, newParts), true); } return(null); }
public void Setup() { _engine = new OsmiumEngine(); _blank = _engine.Expr(_engine.Sym("System`Blank")); _blankSeq = _engine.Expr(_engine.Sym("System`BlankSequence")); _blankNullSeq = _engine.Expr(_engine.Sym("System`BlankNullSequence")); }
public ExpressionValue(OsmiumEngine engine, Value head, params Value[] parts) : base(engine) { Head = head ?? throw new ArgumentNullException(nameof(head)); Parts = parts ?? throw new ArgumentNullException(nameof(parts)); AtomHead = Head.AtomHead; }
public static Value Parse(OsmiumEngine engine, string input) { var lines = input.Split('\n'); var lex = new WolframLanguageLexer(new AntlrInputStream(input)); var parse = new WolframLanguageParser(new CommonTokenStream(lex, Lexer.DefaultTokenChannel)); lex.Parser = parse; var listen = new ExprBuildListener(engine, parse); var errors = new List <string>(); parse.AddErrorListener(new ErrorListener <IToken>((recognizer, token, line, pos, msg, e) => { errors.Add($"Unexpected {token} at {line}:{pos}: {msg}"); })); var expr = parse.expr(); ParseTreeWalker.Default.Walk(listen, expr); if (errors.Any()) { foreach (var i in errors) { Console.WriteLine("err: {0}", i); } return(null); } return(listen.GetValue()); }
public static (Value, bool)? SetDelayed(OsmiumEngine engine, ExpressionValue expr) { if (expr.Count != 2) { // TODO: message } var lhs = expr[0]; var rhs = expr[1]; switch (lhs) { case ExpressionValue lhsExpr: // TODO: make sure head is a symbol DoSet(engine.PatternMatching.CompilePattern(lhsExpr), lhsExpr.SymbolHead, lhsExpr.SymbolHead.DownValues, rhs); break; case Symbol lhsSymbol: DoSet(engine.PatternMatching.CompilePattern(lhsSymbol), lhsSymbol, lhsSymbol.OwnValues, rhs); break; default: // TODO: message break; } return(engine.System.Null, false); }
private static Value DoApply(OsmiumEngine engine, Value f, Value target, int lvlFrom, int lvlTo) { if (target is ExpressionValue expr) { return(engine.Expr(f, expr.Parts.ToArray())); } return(target); }
public static (Value, bool)? Plus(OsmiumEngine engine, ExpressionValue value) { if (!(value.Head is Symbol sv) || sv != engine.System.Plus) { return(null); } return(NumericOp(engine, value, engine.Zero, NumericOperations.Add)); }
private static Value ApplyIfDefined(OsmiumEngine engine, Symbol sym, Value value) { if (engine.System.SPreRead.HasOwnValue()) { value = engine.Evaluate(engine.Expr(sym, value)); } return(value); }
private static (Value, bool)? NumericOp(OsmiumEngine engine, ExpressionValue value, NumberValue identity, NumericOperations.NumericFunction op) { NumberValue nv = null; int numCount = 0; var nonNum = new List <Value>(); foreach (var part in value) { if (!(part is NumberValue numPart)) { nonNum.Add(part); continue; } numCount++; nv = nv == null ? numPart : op(nv, numPart); } if (nonNum.Count == 0) // there were no non-numbers ( 1 + 2 ) -> 3 { return(nv, true); } if (nv == null) // no number was found (x + y) { return(value, false); } if (nv.Equals(identity)) // total of numbers was the identity element ( x + y + 1 - 1 ) -> ( x + y ) { if (nonNum.Count == 1) // exactly one non-number ( x + 1 - 1 ) -> x { return(nonNum[0], true); } // multiple non-numbers, keep the Plus head return(engine.Expr(value.Head, nonNum.ToArray()), true); } if (numCount == 1) // there was exactly one number, nothing changed (x + 1) -> (x + 1) { return(value, false); } // there were multiple numbers, add the result and keep the rest (x + y + 1 + 2) -> (x + y + 3) nonNum.Add(nv); return(engine.Expr(value.Head, nonNum.ToArray()), true); }
public static (Value, bool)? Times(OsmiumEngine engine, ExpressionValue value) { if (!(value.Head is Symbol sv) || sv != engine.System.Times) { return(null); } if (value.Count == 2 && value[0].Equals(engine.MinusOne) && value[1] is NumberValue number) { return(number.Neg(), true); // short-circuit form for Times[-1, x] } return(NumericOp(engine, value, engine.Zero, NumericOperations.Mul)); }
public RationalValue(OsmiumEngine engine, BigInteger numerator, BigInteger denominator) : base(engine) { if (denominator.Sign < 0) { numerator = -numerator; denominator = -denominator; } var gcd = GCD(numerator, denominator); if (gcd != 1) { numerator /= gcd; denominator /= gcd; } Numerator = numerator; Denominator = denominator; }
public static (Value, bool)? And(OsmiumEngine engine, ExpressionValue expr) { var pts = new List <Value>(); bool noChange = true; foreach (var part in expr.Parts) { var epart = engine.Evaluate(part); if (epart is Symbol sv) { if (sv == engine.System.False) { return(epart, false); } if (sv == engine.System.True) { continue; } } noChange = noChange && epart.Equals(part); pts.Add(epart); } if (pts.Count == 0) { return(engine.System.True, false); } if (pts.Count == 1) { return(pts[0], false); } return(engine.Expr(engine.System.And, pts.ToArray() ), false); }
private static void AddDownValue(OsmiumEngine engine, Symbol sym, Value value, params Value[] args) { sym.DownValues.Append((engine.PatternMatching.CompilePattern(engine.Expr(sym, args)), value)); }
static void Main(string[] args) { var prompt = true; if (prompt) { Console.WriteLine("Osmium Kernel"); } var engine = new OsmiumEngine(); while (true) { if (!engine.System.SLine.HasOwnValue()) { // $Line = 1 engine.Set(engine.System.SLine, engine.One); } if (prompt) { Console.WriteLine(); Console.Write("In[{0}]:= ", engine.System.SLine.GetValue()); } var input = Console.ReadLine(); input = (ApplyIfDefined(engine, engine.System.SPreRead, engine.Str(input)) as StringValue)?.Value ?? ""; var parsed = engine.Parse(input); if (parsed == null) { continue; } AddDownValue(engine, engine.System.InString, engine.Str(input), engine.System.SLine); AddDownValue(engine, engine.System.In, parsed, engine.System.SLine); var output = engine.Evaluate(engine.System.SPre.HasOwnValue() ? engine.Expr(engine.System.SPre, parsed) : parsed); output = ApplyIfDefined(engine, engine.System.SPost, output); AddDownValue(engine, engine.System.Out, output); engine.SetDelayed( engine.Expr(engine.System.MessageList, engine.System.SLine), engine.System.SMessageList.HasOwnValue() ? engine.System.SMessageList.GetValue() : engine.List() ); if (!output.Equals(engine.Null)) { output = ApplyIfDefined(engine, engine.System.SPrePrint, output); if (prompt) { Console.WriteLine(); Console.WriteLine("Out[{0}]= {1}", engine.System.SLine.GetValue(), output); } else { Console.WriteLine(output); } } engine.Evaluate(engine.Expr(engine.System.Increment, engine.System.SLine)); } }
public ExprPattern(OsmiumEngine engine, Pattern head, Pattern[] parts) { _engine = engine; _head = head; _parts = parts; }
public PatternMatching(OsmiumEngine engine) { _engine = engine; }
public RealValue(OsmiumEngine engine, double value) : base(engine) { Value = value; }
public IntegerValue(OsmiumEngine engine, BigInteger value) : base(engine) { Value = value; }
protected Value(OsmiumEngine engine) { Engine = engine; }
public ComplexValue(OsmiumEngine engine, NumberValue real = null, NumberValue complex = null) : base(engine) { Real = real ?? Engine.Zero; Imag = complex ?? Engine.Zero; }
public void SetUp() { _e = new OsmiumEngine(); }
protected AtomicValue(OsmiumEngine engine) : base(engine) { }
public Evaluator(OsmiumEngine engine) { _engine = engine; }
public ExprBuildListener(OsmiumEngine engine, WolframLanguageParser parse) { _engine = engine; _parse = parse; }
public StringValue(OsmiumEngine engine, string value) : base(engine) { Value = value ?? throw new ArgumentNullException(nameof(value)); }
private RationalValue(OsmiumEngine engine, BigInteger numerator, BigInteger denominator, bool unused) : base(engine) { Numerator = numerator; Denominator = denominator; }
protected NumberValue(OsmiumEngine engine) : base(engine) { }