/// <param name="ocn"> /// Object constructor node with the initialisation code /// for this layer of initialisation. /// </param> /// <param name="s"> /// Lexical scope the initialisation code will be executed in. /// </param> /// <param name="map"> /// Mapping of declaration nodes to storage cells. /// </param> public UserObjectInitialiser( ObjectConstructorNode ocn, Interpreter.ScopeMemo s, Dictionary <Node, Cell> map ) { constructor = ocn; scope = s; cellMapping = map; }
/// <summary> /// Create an ordinary method node. /// </summary> /// <param name="c"> /// Method node with code to run for this method /// </param> /// <param name="scope"> /// Captured lexical scope /// </param> public Method(MethodNode c, Interpreter.ScopeMemo scope) { code = c; if (c != null) { Confidential = c.Confidential; Abstract = c.Abstract; } lexicalScope = scope; }
private GraceBlock(EvaluationContext ctx, List <Node> parameters, List <Node> body, BlockNode node) { this.parameters = parameters; this.body = body; this.node = node; lexicalScope = ctx.Memorise(); applyName = MethodHelper.ArityNamePart("apply", parameters.Count); AddMethod(applyName, null); AddMethod("spawn", null); AddMethod("asString", null); if (parameters.Count == 1) { AddMethod("match(_)", null); AddMethod("|(_)", Matching.OrMethod); AddMethod("&(_)", Matching.AndMethod); var par = parameters[0]; var first = par as ParameterNode; if (first != null && first.Type != null) { Pattern = first.Type.Evaluate(ctx); } else if (par is NumberLiteralNode || par is StringLiteralNode || par is ExplicitReceiverRequestNode) { Pattern = par.Evaluate(ctx); explicitPattern = true; var t = par.Location; var id = new IdentifierParseNode( new IdentifierToken(t.module, t.line, t.column, "_")); this.parameters = new List <Node> { new ParameterNode(t, id) }; } } }
/// <summary> /// REPL-execute a given line in an interpreter, /// indicating whether it was incomplete, and /// restoring the interpreter afterwards. /// </summary> /// <param name="interp"> /// Interpreter to use /// </param> /// <param name="obj"> /// Module object where method declarations will be added. /// </param> /// <param name="memo"> /// Restoration point for the interpreter context. /// </param> /// <param name="line"> /// Line of code to execute. /// </param> /// <param name="unfinished"> /// Set to true if this line was incomplete and could not /// be executed for that reason. /// </param> /// <param name="result"> /// Result of the executed expression. /// </param> public static int RunLine(Interpreter interp, UserObject obj, Interpreter.ScopeMemo memo, string line, out bool unfinished, out GraceObject result) { result = null; ParseNode module; ObjectConstructorNode mod = null; var isExtensionTrait = false; try { var p = new Parser("source code", line); module = p.Parse(); var opm = (ObjectParseNode)module; if (opm.Body.Count == 1) { // Tricky hack to let extensions be defined interactively. var trait = opm.Body[0] as TraitDeclarationParseNode; isExtensionTrait = (trait != null && trait.Signature.Name.EndsWith("Extension")); } var trans = new ExecutionTreeTranslator(); mod = (ObjectConstructorNode)trans.Translate(opm); } catch (StaticErrorException ex) { if (ex.Code == "P1001") { // "Unexpected end of file" is expected in the // repl for unfinished statements. unfinished = true; return(1); } else { // All other errors are errors. unfinished = false; return(1); } } unfinished = false; if (mod != null) { try { // The "module" object can only really have // a single element, but we don't know whether // it's a method, statement, or expression yet. foreach (var meth in mod.Methods.Values) { obj.AddMethod(meth.Name, new Method(meth, memo)); } foreach (var node in mod.Body) { var inherits = node as InheritsNode; if (inherits != null) { var ms = inherits.Inherit(interp, obj); obj.AddMethods(ms); obj.RunInitialisers(interp); } var v = node as VarDeclarationNode; var d = node as DefDeclarationNode; Cell cell; var meths = new Dictionary <string, Method>(); if (v != null) { obj.CreateVar(v.Name, meths, v.Readable, v.Writable, out cell); obj.AddMethods(meths); if (v.Value != null) { cell.Value = v.Value.Evaluate(interp); } result = GraceObject.Done; continue; } if (d != null) { obj.CreateDef(d.Name, meths, d.Public, out cell); obj.AddMethods(meths); cell.Value = d.Value.Evaluate(interp); result = GraceObject.Done; continue; } var ret = node.Evaluate(interp); if (ret != null && ret != GraceObject.Done && ret != GraceObject.Uninitialised) { interp.Print(interp, ret); } result = ret; } if (isExtensionTrait) { interp.LoadExtensionsFromObject(obj); } } catch (GraceExceptionPacketException e) { ErrorReporting.WriteLine("Uncaught exception:"); ErrorReporting.WriteException(e.ExceptionPacket); if (e.ExceptionPacket.StackTrace != null) { foreach (var l in e.ExceptionPacket.StackTrace) { ErrorReporting.WriteLine(" from " + l); } } return(1); } finally { // No matter what happened, restore the interpreter // to as pristine a state as we can manage before // the next time. interp.RestoreExactly(memo); interp.PopCallStackTo(0); mod = null; } } return(0); }