void AccessExpr(out ElaExpression exp) { Literal(out exp); while (la.kind == 27) { Get(); if (la.kind == 54) { Get(); if (la.kind == 1) { Get(); } else if (la.kind == 2) { Get(); } else if (StartOf(20)) { Operators(); } else SynErr(92); exp = new ElaFieldReference(t) { FieldName = t.val, TargetObject = exp }; Expect(55); } else if (la.kind == 1 || la.kind == 2) { if (la.kind == 1) { Get(); } else { Get(); } exp = new ElaFieldReference(t) { FieldName = t.val, TargetObject = exp }; } else SynErr(93); } }
//Checks if a field reference is actually an exported name prefixed by a module //and if so emits a direct Pushexit op typeId. If this is not the case returns false //and the typeId gets compiled as a regular field reference. private bool TryOptimizeFieldReference(ElaFieldReference p) { if (p.TargetObject.Type != ElaNodeType.NameReference) return false; var mod = default(ModuleReference); var sv = GetVariable(p.TargetObject.GetName(), p.TargetObject.Line, p.TargetObject.Column); //Looks like a target object is not a module if ((sv.Flags & ElaVariableFlags.Module) != ElaVariableFlags.Module || !frame.References.TryGetValue(p.TargetObject.GetName(), out mod)) return false; var fieldSv = default(ScopeVar); //We have such a reference but looks like it couldn't be obtained //We don't need to handle this situation here, it is already reported by a linker if (refs[mod.LogicalHandle] == null) return false; //No such name, now captured statically if (!refs[mod.LogicalHandle].GlobalScope.Locals.TryGetValue(p.FieldName, out fieldSv) && !options.IgnoreUndefined) { AddError(ElaCompilerError.UndefinedNameInModule, p, p.TargetObject.GetName(), p.FieldName); return false; } //Name is private, now captured statically if ((fieldSv.VariableFlags & ElaVariableFlags.Private) == ElaVariableFlags.Private) { AddError(ElaCompilerError.PrivateNameInModule, p, p.FieldName, p.TargetObject.GetName()); return false; } AddLinePragma(p); cw.Emit(Op.Pushext, mod.LogicalHandle | fieldSv.Address << 8); return true; }