Пример #1
0
            public override BuiltinArg Process(Compilation cc, Action <string> error, ZilObject arg, ParameterInfo pi)
            {
                var quirks = pi.GetCustomAttributes <VariableAttribute>().Single().QuirksMode;

                // arg must be an atom, or <GVAL atom> or <LVAL atom> in quirks mode
                var atom = arg as ZilAtom;

                if (atom == null && !((quirks & QuirksMode.Global) != 0 && arg.IsGVAL(out atom) ||
                                      (quirks & QuirksMode.Local) != 0 && arg.IsLVAL(out atom)))
                {
                    error("argument must be a variable");
                    return(new BuiltinArg(BuiltinArgType.Operand, null));
                }

                if (pi.ParameterType == typeof(IVariable))
                {
                    if (!cc.Locals.ContainsKey(atom) && !cc.Globals.ContainsKey(atom))
                    {
                        error("no such variable: " + atom);
                    }

                    var variableRef = GetVariable(cc, arg, quirks);
                    return(new BuiltinArg(BuiltinArgType.Operand, variableRef?.Hard));
                }
                else // if (pi.ParameterType == typeof(SoftGlobal))
                {
                    if (!cc.SoftGlobals.ContainsKey(atom))
                    {
                        error("no such variable: " + atom);
                    }

                    var variableRef = GetVariable(cc, arg, quirks);
                    return(new BuiltinArg(BuiltinArgType.Operand, variableRef?.Soft));
                }
            }
Пример #2
0
        static bool CheckFormOrSegment([NotNull] Context ctx, [NotNull] ZilObject value, [NotNull] ZilForm form,
                                       bool segment, bool ignoreErrors)
        {
            var(first, rest) = form;

            // special forms
            // ReSharper disable once SwitchStatementMissingSomeCases
            switch ((first as ZilAtom)?.StdAtom)
            {
            case StdAtom.OR:
                return(rest.Any(subpattern => Check(ctx, value, subpattern, ignoreErrors)));

            case StdAtom.QUOTE:
                return(rest.First?.StructurallyEquals(value) ?? false);

            case StdAtom.PRIMTYPE when rest.First is ZilAtom primType:
                // special case for GVAL and LVAL, which can substitute for <PRIMTYPE ATOM>
                return
                    (value.PrimType == ctx.GetTypePrim(primType) ||
                     primType.StdAtom == StdAtom.ATOM &&
                     (value.IsGVAL(out _) || value.IsLVAL(out _)));
            }

            // structure form: first pattern element is a DECL matched against the whole structure
            // (usually a type atom), remaining elements are matched against the structure elements
            if (first == null || !Check(ctx, value, first, ignoreErrors))
            {
                return(false);
            }

            if (value is IStructure valueAsStructure)
            {
                // yay
            }
            else if (value is IProvideStructureForDeclCheck structProvider)
            {
                valueAsStructure = structProvider.GetStructureForDeclCheck(ctx);
            }
            else
            {
                return(false);
            }

            return(CheckElements(ctx, valueAsStructure, rest, segment, ignoreErrors));
        }
Пример #3
0
        public static ZilObject TYPE_P([NotNull] Context ctx, [NotNull] ZilObject value, [NotNull][Required] ZilAtom[] types)
        {
            var type = value.GetTypeAtom(ctx);

            foreach (var candidate in types)
            {
                if (candidate == type)
                {
                    return(candidate);
                }

                // Special case for LVAL/GVAL
                if (candidate.StdAtom == StdAtom.LVAL && value.IsLVAL(out _) ||
                    candidate.StdAtom == StdAtom.GVAL && value.IsGVAL(out _))
                {
                    return(candidate);
                }
            }

            return(ctx.FALSE);
        }
Пример #4
0
        static VariableRef?GetVariable([NotNull] Compilation cc, [NotNull] ZilObject expr, QuirksMode quirks = QuirksMode.None)
        {
            if (!(expr is ZilAtom atom) &&
                ((quirks & QuirksMode.Global) == 0 || !expr.IsGVAL(out atom)) &&
                ((quirks & QuirksMode.Local) == 0 || !expr.IsLVAL(out atom)))
            {
                return(null);
            }

            if (quirks == QuirksMode.Global)
            {
                // prefer global over local
                if (cc.Globals.TryGetValue(atom, out var gb))
                {
                    return(new VariableRef(gb));
                }
                if (cc.Locals.TryGetValue(atom, out var lbr))
                {
                    return(new VariableRef(lbr.LocalBuilder));
                }
            }
            else
            {
                if (cc.Locals.TryGetValue(atom, out var lbr))
                {
                    return(new VariableRef(lbr.LocalBuilder));
                }
                if (cc.Globals.TryGetValue(atom, out var gb))
                {
                    return(new VariableRef(gb));
                }
            }

            if (cc.SoftGlobals.TryGetValue(atom, out var sg))
            {
                return(new VariableRef(sg));
            }

            return(null);
        }
Пример #5
0
        public static bool Check([NotNull] Context ctx, [NotNull] ZilObject value, [NotNull] ZilObject pattern,
                                 bool ignoreErrors = false)
        {
            switch (pattern)
            {
            case ZilAtom atom:
                // ReSharper disable once SwitchStatementMissingSomeCases
                switch (atom.StdAtom)
                {
                case StdAtom.ANY:
                    return(true);

                case StdAtom.APPLICABLE:
                    return(value.IsApplicable(ctx));

                case StdAtom.STRUCTURED:
                    return(value is IStructure);

                case StdAtom.TUPLE:
                    // special case
                    return(value.StdTypeAtom == StdAtom.LIST);

                default:
                    // arbitrary atoms can be type names...
                    if (ctx.IsRegisteredType(atom))
                    {
                        var typeAtom = value.GetTypeAtom(ctx);

                        if (typeAtom == atom)
                        {
                            return(true);
                        }

                        // special cases: a raw TABLE value can substitute for a TABLE-based type, or VECTOR
                        return(typeAtom.StdAtom == StdAtom.TABLE &&
                               (atom.StdAtom == StdAtom.VECTOR || ctx.GetTypePrim(atom) == PrimType.TABLE));
                    }

                    // ...or aliases
                    if (IsNonCircularAlias(ctx, atom, out var aliased))
                    {
                        return(Check(ctx, value, aliased, ignoreErrors));
                    }

                    // special cases for GVAL and LVAL
                    // ReSharper disable once SwitchStatementMissingSomeCases
                    switch (atom.StdAtom)
                    {
                    case StdAtom.GVAL:
                        return(value.IsGVAL(out _));

                    case StdAtom.LVAL:
                        return(value.IsLVAL(out _));

                    default:
                        return(ignoreErrors
                                        ? false
                                        : throw new InterpreterError(
                                   InterpreterMessages.Unrecognized_0_1,
                                   "atom in DECL pattern",
                                   atom));
                    }
                }

            case ZilSegment seg:
                return(CheckFormOrSegment(ctx, value, seg.Form, true, ignoreErrors));

            case ZilForm form:
                return(CheckFormOrSegment(ctx, value, form, false, ignoreErrors));

            default:
                if (ignoreErrors)
                {
                    return(false);
                }

                throw new InterpreterError(
                          InterpreterMessages.Unrecognized_0_1,
                          "value in DECL pattern",
                          pattern.ToStringContext(ctx, false));
            }
        }
Пример #6
0
 static bool IsSimpleOutputElement([NotNull] ZilObject obj)
 {
     return(obj is ZilAtom || obj is ZilFix || obj is ZilString || obj is ZilFalse ||
            obj.IsLVAL(out _) || obj.IsGVAL(out _));
 }