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)); } }
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)); }
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); }
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); }
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)); } }
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 _)); }