Example #1
0
        public RuntimeResult InitializeBaseClass(Context ctx, Interpreter interpreter)
        {
            if (BaseClass != null)
            {
                ClassValue classValue = ((ClassValue)BaseClass).Clone();
                if (classValue.BaseClass != null)
                {
                    RuntimeResult baseResult = classValue.InitializeBaseClass(ctx, interpreter);
                    if (baseResult.HasError)
                    {
                        return(baseResult);
                    }

                    Context newContext = new Context(BaseName, baseResult.Value.Context);
                    classValue.SetPositionAndContext(Position, newContext);
                    newContext.AddSymbol("this", classValue);
                    newContext.AddSymbol("base", baseResult.Value);
                    return(interpreter.Visit(classValue.Body, newContext));
                }
                else
                {
                    Context newContext = new Context(BaseName, ctx);
                    classValue.SetPositionAndContext(Position, newContext);
                    newContext.AddSymbol("this", classValue);
                    return(interpreter.Visit(classValue.Body, newContext));
                }
            }
            return(new RuntimeResult(new RuntimeError(Position, "Base class '" + BaseName + "' not found!", ctx)));
        }
Example #2
0
        private RuntimeResult VisitCallNode(CallNode node, Context context, Context fromCtx = null)
        {
            List <(string, Values.Value)> args = new List <(string, Values.Value)>();

            for (int i = 0; i < node.Arguments.Count; i++)
            {
                RuntimeResult result = Visit(node.Arguments[i].Item2, fromCtx == null ? context : fromCtx);
                if (result.HasError)
                {
                    return(result);
                }
                args.Add((node.Arguments[i].Item1, result.Value));
            }
            if (node.Node.Type == NodeType.VAR_ACCESS)
            {
                VarAccessNode accessNode = (VarAccessNode)node.Node;
                string        name       = accessNode.Token.Value.ToString();
                if (BuiltinMethods.BuiltinMethodList.ContainsKey(name))
                {
                    return(BuiltinMethods.Execute(name, args, node.Position, context));
                }
                else
                {
                    Values.Value method = context.GetSymbol(name);
                    if (method == null)
                    {
                        return(new RuntimeResult(new RuntimeError(node.Position, "Method '" + name + "' is not defined", context)));
                    }
                    if (method.Type == Values.ValueType.METHOD)
                    {
                        return(((Values.MethodValue)method).Execute(args, this));
                    }
                    else if (method.Type == Values.ValueType.CLASS)
                    {
                        Values.ClassValue classValue = ((Values.ClassValue)method).Clone();
                        //classValue.Type = Values.ValueType.OBJECT;
                        if (classValue.BaseClass != null)
                        {
                            RuntimeResult baseResult = classValue.InitializeBaseClass(context, this);
                            if (baseResult.HasError)
                            {
                                return(baseResult);
                            }

                            Context newContext = new Context(name, baseResult.Value.Context);
                            classValue.SetPositionAndContext(accessNode.Token.Position, newContext);
                            newContext.AddSymbol("this", classValue);
                            newContext.AddSymbol("base", baseResult.Value);
                            RuntimeResult runtimeResult = Visit(classValue.Body, newContext);
                            if (runtimeResult.HasError)
                            {
                                return(runtimeResult);
                            }

                            //Constructor
                            Values.Value ctorValue = newContext.GetSymbol("init");
                            if (ctorValue != null && ctorValue.Type == Values.ValueType.METHOD)
                            {
                                Values.MethodValue initMethod = (Values.MethodValue)ctorValue;
                                RuntimeResult      res        = initMethod.Execute(args, this);
                                if (res.HasError)
                                {
                                    return(res);
                                }
                            }
                            return(new RuntimeResult(classValue));
                        }
                        else
                        {
                            Context newContext = new Context(name, context);
                            classValue.SetPositionAndContext(accessNode.Token.Position, newContext);
                            newContext.AddSymbol("this", classValue);
                            RuntimeResult runtimeResult = Visit(classValue.Body, newContext);
                            if (runtimeResult.HasError)
                            {
                                return(runtimeResult);
                            }

                            //Constructor
                            Values.Value ctorValue = newContext.GetSymbol("init");
                            if (ctorValue != null && ctorValue.Type == Values.ValueType.METHOD)
                            {
                                Values.MethodValue initMethod = (Values.MethodValue)ctorValue;
                                initMethod.Execute(args, this);
                            }
                            return(new RuntimeResult(classValue));
                        }
                    }
                    return(new RuntimeResult(new RuntimeError(node.Position, "'" + name + "' is not a method", context)));
                }
            }
            return(new RuntimeResult(new RuntimeError(node.Position, "Can't call as a method", context)));
        }