UNPKG

minigrace

Version:

A compiler for the Grace programming language

815 lines 395 kB
let gracecode_identifierresolution_sourceFile = "/Users/black/Development/mg/gracelang/minigrace/identifierresolution.grace"; let gracecode_identifierresolution_sha256 = "62acc99085ba3f1f41622f27effe11098756887354dc896492bafc83d1128d27"; let gracecode_identifierresolution_minigraceRevision = "b57591d29fc5ee5270d114920bf671367b8c3ecb"; let gracecode_identifierresolution_minigraceGeneration = "5171"; if (typeof gctCache !== "undefined") gctCache["identifierresolution"] = "dialect:\n standard\nfreshScopes:\n $102\n $103\n $104\n $105\n $107\nmethodTypes:$101:\n addGctLine(gctLine:String)toScope(s:Unknown)for(gct:Unknown) \u2192 Unknown\n methodSignature(methNode:Unknown) \u2192 String\n readerSignature(declNode:Unknown) \u2192 String\n transformCall(cNode:Unknown) \u2192 ast.AstNode\n writerSignature(declNode:Unknown) \u2192 String\nmodules:\n ast\n basic\n constantScope\n errormessages\n io\n scope\n standard\n sys\n util\n xmodule\npath:\n /Users/black/Development/mg/gracelang/minigrace/identifierresolution.grace\nscope:$101:\n AstNode type\n CompilerError Unknown (mth) $scope_done\n GatheringError Unknown (mth) $scope_done\n HasName type\n Position type\n Range type\n Scope type\n Variable type\n addGctLine(1)toScope(1)for(1) Unknown (mth) $scope_done\n articleFor(1) Unknown (mth) $scope_done\n asDebugString String (go) $scope_string\n asString String (go) $scope_string\n basicAsString String (go) $scope_string\n buildSymbolTableFor(1)ancestors(1) Unknown (mth) $scope_done\n canonicalName(1) Unknown (mth) $scope_done\n checkForConflicts(2) Unknown (mth) $scope_done\n checkTraitBody(1) Unknown (mth) $scope_done\n collectReusedNames(1) Unknown (mth) $scope_done confidential\n conflictForMethodName(1)from(1) Unknown (mth) $103\n earlyReturnVis Unknown (mth) $102\n emptyRange Unknown (mth) $scope_done\n ensureOuterScopesCollected(1) Unknown (mth) $scope_done\n fakeSymbolTable Unknown (mth) $104\n gatherInheritedNames(1) Unknown (mth) $scope_done confidential\n gatherUsedNames(1) Unknown (mth) $scope_done confidential\n generateGctForModule(1) Unknown (mth) $scope_done\n generateOneselfRequestFrom(1)using(1) Unknown (mth) $scope_done\n isMe(1) Boolean (go) $scope_boolean\n line(1)column(1) Position (mth) $105\n methodSignature(1) String (mth) $scope_done\n myIdentityHash Number (go) $scope_number\n noPosition Unknown (mth) $scope_done\n nullNode AstNode (mth) $106\n numTypeParams(1) Unknown (mth) $scope_done confidential\n numericName(1) Unknown (mth) $scope_done\n processGct(2) Unknown (mth) $scope_done\n readerSignature(1) String (mth) $scope_done\n resolve(1) Unknown (mth) $scope_done\n resolveIdentifiers(1) Unknown (mth) $scope_done\n reusedScope(1) Unknown (mth) $scope_done\n scopeReferencedByReuseExpr(1) Unknown (mth) $scope_done\n scopeWithUid(1)for(1) Unknown (mth) $scope_done\n sequenceNr Unknown (mth) $scope_done\n serializeVariable(1)withName(1)in(1) Unknown (mth) $scope_done\n setupContext(1) Unknown (mth) $scope_done\n start(1)end(1) Range (mth) $107\n transformBind(1)ancestors(1) Unknown (mth) $scope_done\n transformCall(1) AstNode (mth) $scope_done\n transformIdentifier(1)ancestors(1) Unknown (mth) $scope_done\n transformReuse(1)ancestors(1) Unknown (mth) $scope_done\n typeName(1)in(1) Unknown (mth) $scope_done\n writeGctForModule(1) Unknown (mth) $scope_done\n writerSignature(1) String (mth) $scope_done\nscope:$102:\n asDebugString String (go) $scope_string\n asString Unknown (mth) $scope_done\n basicAsString String (go) $scope_string\n containsEarlyReturn Unknown (var) $scopeEmpty readable\n containsEarlyReturn:=(1) Unknown (var) $scopeEmpty readable\n isMe(1) Boolean (go) $scope_boolean\n myIdentityHash Number (go) $scope_number\n visitAlias(1) Boolean (mth) $scope_done\n visitAlias(1)up(1) Boolean (mth) $scope_done\n visitAssignment(1) Boolean (mth) $scope_done\n visitAssignment(1)up(1) Unknown (mth) $scope_done\n visitBlock(1) Boolean (mth) $scope_done\n visitBlock(1)up(1) Unknown (mth) $scope_done\n visitComment(1) Boolean (mth) $scope_done\n visitComment(1)up(1) Unknown (mth) $scope_done\n visitDefDec(1) Boolean (mth) $scope_done\n visitDefDec(1)up(1) Unknown (mth) $scope_done\n visitDialect(1) Boolean (mth) $scope_done\n visitDialect(1)up(1) Unknown (mth) $scope_done\n visitEllipsis(1) Boolean (mth) $scope_done\n visitEllipsis(1)up(1) Unknown (mth) $scope_done\n visitIdentifier(1) Boolean (mth) $scope_done\n visitIdentifier(1)up(1) Unknown (mth) $scope_done\n visitIf(1) Boolean (mth) $scope_done\n visitIf(1)up(1) Unknown (mth) $scope_done\n visitImplicit(1) Boolean (mth) $scope_done\n visitImplicit(1)up(1) Unknown (mth) $scope_done\n visitImport(1) Boolean (mth) $scope_done\n visitImport(1)up(1) Unknown (mth) $scope_done\n visitInherit(1) Boolean (mth) $scope_done\n visitInherit(1)up(1) Unknown (mth) $scope_done\n visitInterfaceLiteral(1) Boolean (mth) $scope_done\n visitInterfaceLiteral(1)up(1) Unknown (mth) $scope_done\n visitMatchCase(1) Boolean (mth) $scope_done\n visitMatchCase(1)up(1) Unknown (mth) $scope_done\n visitMethodDec(1) Boolean (mth) $scope_done\n visitMethodDec(1)up(1) Unknown (mth) $scope_done\n visitMethodSignature(1) Boolean (mth) $scope_done\n visitMethodSignature(1)up(1) Unknown (mth) $scope_done\n visitModule(1) Boolean (mth) $scope_done\n visitModule(1)up(1) Unknown (mth) $scope_done\n visitNumeral(1) Boolean (mth) $scope_done\n visitNumeral(1)up(1) Unknown (mth) $scope_done\n visitObject(1) Unknown (mth) $scope_done\n visitObject(1)up(1) Unknown (mth) $scope_done\n visitOp(1) Boolean (mth) $scope_done\n visitOp(1)up(1) Unknown (mth) $scope_done\n visitRequest(1) Boolean (mth) $scope_done\n visitRequest(1)up(1) Unknown (mth) $scope_done\n visitRequestWithoutArgs(1) Boolean (mth) $scope_done\n visitRequestWithoutArgs(1)up(1) Unknown (mth) $scope_done\n visitReturn(1) Unknown (mth) $scope_done\n visitReturn(1)up(1) Unknown (mth) $scope_done\n visitSelfType(1) Boolean (mth) $scope_done\n visitSelfType(1)up(1) Boolean (mth) $scope_done\n visitSequence(1) Boolean (mth) $scope_done\n visitSequence(1)up(1) Unknown (mth) $scope_done\n visitSignaturePart(1) Boolean (mth) $scope_done\n visitSignaturePart(1)up(1) Unknown (mth) $scope_done\n visitString(1) Boolean (mth) $scope_done\n visitString(1)up(1) Unknown (mth) $scope_done\n visitTryCatch(1) Boolean (mth) $scope_done\n visitTryCatch(1)up(1) Unknown (mth) $scope_done\n visitTypeApplication(1) Boolean (mth) $scope_done\n visitTypeApplication(1)up(1) Unknown (mth) $scope_done\n visitTypeDec(1) Boolean (mth) $scope_done\n visitTypeDec(1)up(1) Unknown (mth) $scope_done\n visitTypeParameters(1) Boolean (mth) $scope_done\n visitTypeParameters(1)up(1) Unknown (mth) $scope_done\n visitUniversalDec(1) Boolean (mth) $scope_done\n visitUniversalDec(1)up(1) Unknown (mth) $scope_done\n visitUnknown(1) Boolean (mth) $scope_done\n visitUnknown(1)up(1) Unknown (mth) $scope_done\n visitVarDec(1) Boolean (mth) $scope_done\n visitVarDec(1)up(1) Unknown (mth) $scope_done\n visitYourself(1) Boolean (mth) $scope_done\n visitYourself(1)up(1) Boolean (mth) $scope_done\nscope:$103:\n asDebugString String (go) $scope_string\n asString String (go) $scope_string\n basicAsString String (go) $scope_string\n canonicalName Unknown (mth) $scope_done\n isMe(1) Boolean (go) $scope_boolean\n methodName Unknown (def) $scopeEmpty public\n myIdentityHash Number (go) $scope_number\n sources Unknown (def) $scopeEmpty public\nscope:$104:\n ::(1) Unknown (mth) $scope_done\n ==(1) Unknown (mth) $scope_done\n areReusedNamesCompleted Unknown (mth) $scope_done\n asDebugString String (go) $scope_string\n asString Unknown (mth) $scope_done\n basicAsString String (go) $scope_string\n hash Unknown (mth) $scope_done\n isFresh Unknown (mth) $scope_done\n isMe(1) Boolean (go) $scope_boolean\n localNames Unknown (mth) $scope_done\n myIdentityHash Number (go) $scope_number\n node Unknown (var) $scopeEmpty\n node:=(1) Unknown (var) $scopeEmpty\n prefix== Unknown (mth) $scope_done\n prefix\u2260 Unknown (mth) $scope_done\n variety Unknown (mth) $scope_done\n varsAreMethods Unknown (mth) $scope_done\n \u2260(1) Unknown (mth) $scope_done\nscope:$105:\n ::(1) Unknown (mth) $scope_done\n <(1) Boolean (mth) $scope_done\n ==(1) Boolean (mth) $scope_done\n >(1) Boolean (mth) $scope_done\n addColumn(1) Unknown (mth) $scope_done\n addLine(1) Unknown (mth) $scope_done\n asDebugString String (go) $scope_string\n asString Unknown (mth) $scope_done\n basicAsString String (go) $scope_string\n column Unknown (def) $scopeEmpty\n hash Number (mth) $scope_done\n isMe(1) Boolean (go) $scope_boolean\n line Unknown (def) $scopeEmpty\n myIdentityHash Number (go) $scope_number\n prefix== Unknown (mth) $scope_done\n prefix\u2260 Unknown (mth) $scope_done\n \u2260(1) Unknown (mth) $scope_done\n \u2264(1) Boolean (mth) $scope_done\n \u2265(1) Boolean (mth) $scope_done\nscope:$106:\n ::(1) Unknown (mth) $scope_done\n ==(1) Unknown (mth) $scope_done\n accept(1)from(1) Unknown (mth) $scope_done\n annotations Unknown (mth) $scope_done\n asDebugString String (go) $scope_string\n asString Unknown (mth) $scope_done\n basicAsString String (go) $scope_string\n childrenDo(1) Unknown (mth) $scope_done\n childrenMap(1) Unknown (mth) $scope_done\n column Unknown (def) $scope_number\n column:=(1) Unknown (mth) $scope_done\n comments Unknown (mth) $scope_done\n decType Unknown (mth) $scope_done\n end Position (mth) $scope_done\n endCol Unknown (mth) $scope_done\n hasAnnotation(1) Unknown (mth) $scope_done\n hash Unknown (mth) $scope_done\n inClass Unknown (mth) $scope_done\n inTrait Unknown (mth) $scope_done\n isAssignment Unknown (mth) $scope_done\n isBlock Unknown (mth) $scope_done\n isBuiltIn Unknown (mth) $scope_done\n isCall Unknown (mth) $scope_done\n isClass Unknown (mth) $scope_done\n isComment Unknown (mth) $scope_done\n isConstant Unknown (mth) $scope_done\n isDeclaredByParent Unknown (mth) $scope_done\n isDialect Unknown (mth) $scope_done\n isExecutable Unknown (mth) $scope_done\n isExternal Unknown (mth) $scope_done\n isFresh Unknown (mth) $scope_done\n isIdentifier Unknown (mth) $scope_done\n isImport Unknown (mth) $scope_done\n isMarkerDeclaration Unknown (mth) $scope_done\n isMe(1) Boolean (go) $scope_boolean\n isMember Unknown (mth) $scope_done\n isMethod Unknown (mth) $scope_done\n isModule Unknown (mth) $scope_done\n isNull Unknown (mth) $scope_done\n isObject Unknown (mth) $scope_done\n isOuter Unknown (mth) $scope_done\n isReturn Unknown (mth) $scope_done\n isSelf Unknown (mth) $scope_done\n isSelfOrOuter Unknown (mth) $scope_done\n isSequenceConstructor Unknown (mth) $scope_done\n isSuper Unknown (mth) $scope_done\n isTrait Unknown (mth) $scope_done\n isTypeDec Unknown (mth) $scope_done\n kind Unknown (def) $scope_string\n line Unknown (def) $scope_number\n line:=(1) Unknown (mth) $scope_done\n map(1)ancestors(1) Unknown (mth) $scope_done\n myIdentityHash Number (go) $scope_number\n nameString Unknown (mth) $scope_done\n newAccept(1) Unknown (mth) $scope_done\n prefix== Unknown (mth) $scope_done\n prefix\u2260 Unknown (mth) $scope_done\n pretty(1) Unknown (mth) $scope_done\n range Unknown (mth) $scope_done\n register Unknown (def) $scope_string\n scope Unknown (def) $104\n shallowCopy Unknown (mth) $scope_done\n start Unknown (mth) $scope_done\n toGrace(1) Unknown (mth) $scope_done\n \u2260(1) Unknown (mth) $scope_done\nscope:$107:\n ::(1) Unknown (mth) $scope_done\n <(1) Unknown (mth) $scope_done\n ==(1) Unknown (mth) $scope_done\n >(1) Unknown (mth) $scope_done\n arrow Unknown (mth) $scope_done\n asDebugString String (go) $scope_string\n asString Unknown (mth) $scope_done\n basicAsString String (go) $scope_string\n column Unknown (mth) $scope_done\n end Unknown (def) $scopeEmpty\n hash Number (mth) $scope_done\n isMe(1) Boolean (go) $scope_boolean\n line Unknown (mth) $scope_done\n lineRangeString Unknown (mth) $scope_done\n myIdentityHash Number (go) $scope_number\n prefix== Unknown (mth) $scope_done\n prefix\u2260 Unknown (mth) $scope_done\n rangeLongString Unknown (mth) $scope_done\n rangeString Unknown (mth) $scope_done\n start Unknown (def) $scopeEmpty\n sugg Unknown (mth) $scope_done\n \u2260(1) Unknown (mth) $scope_done\n \u2264(1) Unknown (mth) $scope_done\n \u2265(1) Unknown (mth) $scope_done\nself:\n $101\ntypedec:$101.HasName:\n type HasName = interface {\n nameString \u2192 String}\ntypes:\n $101.HasName\n"; if (typeof originalSourceLines !== "undefined") { originalSourceLines["identifierresolution"] = [ "dialect \"standard\"", "", "import \"io\" as io", "import \"sys\" as sys", "import \"ast\" as ast", "import \"util\" as util", "import \"xmodule\" as xmodule", "import \"errormessages\" as errormessages", "import \"scope\" as sm", "import \"constantScope\" as constantScope", "import \"basic\" as basic", "", "use basic.open", "", "def completed = singleton \"completed\"", "def inProgress = singleton \"inProgress\"", "def undiscovered = singleton \"undiscovered\"", "// constants used in detecting cyclic inheritance", "", "var stSerial := 100", "", "def keyOrdering = { a, b → a.key.compare(b.key) }", "", "def dialectScope = sm.graceDialectScope.in(constantScope.builtInsScope)", "def moduleScope = sm.moduleScope.in(dialectScope)", "", "def varFieldDecls = list [] // a list of nodes that declare var fields", "", "util.setPosition(0, 0)", "", "method transformIdentifier(anIdentifier) ancestors(anc) {", " // anIdentifier is a (copy of an) ast node that represents an applied", " // occurrence of an identifer id.", " // This method may or may not transform anIdentifier into another ast node.", " // If anIdentifier refers to a variable in a block or method,", " // then it should be left as a variable. However, if it refers to", " // a field of an object, then it is tranformed into a method request.", " // Note that it would be possible for confidential fields of stale objects to", " // be compiled as identifiers. We do not do so, because distinguishing", " // this case seems like a lot of work, and V8 will probably inline the", " // accessors for us anyway", "", " if (anIdentifier.isAssigned) then {", " return anIdentifier // will be transformed to a request by transformBind.", " // Transformation is bottom-up, so this has yet to happen", " }", " def defs = sm.variableResolver.definitionsOf (anIdentifier.name) visibleIn (anIdentifier.scope)", " if (defs.isEmpty) then {", " errormessages.undeclaredIdentifier (anIdentifier)", " }", " if (defs.size > 1) then {", " errormessages.ambiguityError (defs) node (anIdentifier)", " }", " def resolution = defs.first", " def variable = resolution.definition", " if (variable.isMethodOrType) then {", " generateOneselfRequestFrom (anIdentifier) using (resolution)", " } elseif { variable.definingScope.varsAreMethods } then {", " // Anything defined in a fresh scope, including a var, can be overridden,", " // so we need to access it via a request.", " generateOneselfRequestFrom (anIdentifier) using (resolution)", " } else {", " anIdentifier", " }", "}", "", "method generateOneselfRequestFrom (aSourceNode) using (aResolvedVariable) {", " // generates and returns some form of \"self request\" based on aSourceNode.", " // The receiver of the generated request may be a yourselfNode, a bind node,", " // or the identifier for the module or dialect.", "", " def objectsUp = aResolvedVariable.objectsUp", " def nodeScope = aSourceNode.scope", " def outerChain = list.empty", " var s := nodeScope.currentObjectScope", " repeat (objectsUp) times {", " outerChain.addLast(s.node)", " s := s.enclosingObjectScope", " }", " def v = s.variety", " def receiver = if (\"dialect | builtIn | module\".contains(v)) then {", " ast.identifier(\"$\" ++ v, false).setScope (nodeScope)", " } else {", " def ynd = ast.yourselfNode(outerChain.size).setScope(nodeScope)", " ynd.line := aSourceNode.line", " ynd.theObjects := outerChain", " ynd", " }", " def result = if (aSourceNode.numArgs == 0) then {", " ast.requestWithoutArgs (aSourceNode.nameString, receiver)", " } else {", " ast.request (receiver, aSourceNode.parts)", " }", " result.setScope(nodeScope).", " onSelf.", " withGenericArgs (aSourceNode.generics).", " setPositionFrom (aSourceNode)", "}", "", "method resolveIdentifiers(topNode) {", " // Recursively replace bare identifiers with their fully-qualified", " // equivalents. Creates and returns a new AST; map works", " // bottom-up, so by the time a node is mapped, all of its", " // descendents have already been mapped.", "", " def newModule = topNode.map { node, anc →", " if ( node.isAppliedOccurrence ) then {", " transformIdentifier(node) ancestors(anc)", " } elseif { node.isCall } then {", " transformCall(node)", " } elseif { node.isInherits } then {", " transformReuse(node) ancestors(anc)", " } elseif { node.isAssignment } then {", " transformBind(node) ancestors(anc)", " } else {", " node", " }", " } ancestors (ast.ancestorChain.empty)", " newModule", "}", "", "method writeGctForModule(moduleObject) {", " // requested by genjs to write the gct to the generated JS file", "", " xmodule.writeGCT(moduleObject.name, generateGctForModule(moduleObject))", "}", "", "method generateGctForModule(module) {", " // The gct is essentially a representation of module's symbol table.", " // We built this representation by iterating over the symbol table.", " // Older versions of this method used to iterate over the ast,", " // but reused methods are not in the ast, and so were omitted.", " //", " // The Gct should be thought of as a mapping from keys to collections of", " // \"gcLines\". A plain-text version of any gct can be obtained by running", " // tools/eg --gct module.js on the compiled file module.js", " //", " // Important keys are:", " // -- dialect: the name of the dialect in which this module is written", " // (empty if no dialect)", " // -- freshScopes: the uid of every scope that describes a fresh object", " // the uid is tagged with \"trait\" if the object is a trait", " // -- methodTypes:<uid>: the type signatures of all methods defined in scope <uid>", " // -- modules: the names of the directly-imported modules (including the dialect)", " // -- path: the path in the file system where the source code was found", " // -- self: the value is the uid for the moduleScope", " // -- scope:<uid>: the entries in that scope", " // -- types: the declarations of all named types. The name is prefixed", " // by the uid of the scope that defines that type name", " //", " // The lines in a scope:<uid> entry are parsed by addGctLine(_)toScope(_).", " // Each has one of two formats:", " // - <typeName> type", " // this is used for types", " // - <methodName> <declaredType> <kindString> <attributeScope> <attributes>", " // used for everything else.", " // <attributes> is optional, and consists of a comma-separated list of strings", "", " def gct = dictionary.empty", " def theDialect = module.theDialect.moduleName", " def methodList = list.empty", " def typeList = list.empty", " def ms = module.scope", " gct.at \"self\" put [ms.uid]", " def scopesToProcess = set.with(ms)", " def scopesAlreadyProcessed = set.withAll(sm.predefined.values)", "", " var pathCount := 0", " def epl = sys.environ.at \"PATH_LIMIT\"", " def pathLimit = if (epl.isEmpty) then { 1000 } else {epl.asNumber}", "", "", " while { scopesToProcess.isEmpty.not } do {", " def s = scopesToProcess.anyone", " scopesToProcess.remove(s)", " if (scopesAlreadyProcessed.contains(s).not) then {", " scopesAlreadyProcessed.add(s)", " def entries = list.empty", " s.localAndReusedNamesAndValuesDo { vName, v →", " if (v.forGct) then {", " entries.add(serializeVariable (v) withName(vName) in (s))", " def subScope = v.attributeScope", " if (scopesAlreadyProcessed.contains(subScope).not) then {", " if (pathCount < pathLimit) then {", " scopesToProcess.add(subScope)", " pathCount := pathCount + 1", " }", " }", " }", " }", " gct.at \"scope:{s.uid}\" put (entries.sort) // yes, this will store an empty scope", " if (s.methodTypes.isEmpty.not) then {", " gct.at \"methodTypes:{s.uid}\" put (s.methodTypes.values.sorted)", " }", " s.types.keysAndValuesDo { eachType, eachDef →", " gct.at \"typedec:{s.uid}.{eachType}\" put [eachDef]", " typeList.add \"{s.uid}.{eachType}\"", " }", " }", " }", " gct.at \"types\" put (typeList.sort)", " gct.at \"modules\" put (xmodule.externalModules.keys.sorted)", " def p = util.infile.pathname", " gct.at \"path\" put [ if (p.isEmpty) then {", " \"\"", " } elseif { p.startsWith \"/\" } then {", " p", " } else {", " io.realpath(p)", " } ]", " gct.at \"dialect\" put (", " if (theDialect == \"none\") then { [] } else { [theDialect] }", " )", " gct.at \"freshScopes\" put (", " scopesAlreadyProcessed.filter {s -> s.isFresh}.map { s ->", " def traitSuffix = if (s.isTrait) then {", " \" trait\"", " } else {", " \"\"", " }", " s.uid ++ traitSuffix", " }.sorted )", " util.log_verbose \"{pathCount} paths added to gct (limit = {pathLimit})\"", " gct", "}", "", "method serializeVariable (defn) withName(n) in (s) {", " // returns a string representation of the variable defn", " // Note that in the case of a writer method for a variable x,", " // n will be x:=(1), whereas defn.name will be x", "", " if (defn.isType) then { return \"{n} type\" }", " var anns", " if { defn.annotations.isEmpty } then {", " anns := \"\"", " } else {", " anns := \" \"", " defn.annotations.do { each →", " anns := anns ++ each.nameString", " } separatedBy { anns := anns ++ \",\" }", " }", " def attrScp = defn.attributeScope", " def tn = typeName (defn.declaredType) in (attrScp)", " \"{n} {tn} {defn.tag} {attrScp.uid}{anns}\"", "}", "", "type HasName = interface { nameString → String }", "", "method typeName (typeNode) in (scope) {", " // returns a name for the type expression denoted by typeNode.", " // typeNode may be an ast node (identifier or unknownLiteral),", " // a constantScope.typeNode, or a string (such as \"Unknown\").", " // If necessary, creates a name starting with $, and enters it in scope's", " // types dictionary", "", " match(typeNode)", " case { nd:HasName -> nd.nameString", " } case { s:String -> s", " } else {", " def name = \"$type{sequenceNr}\"", " scope.types.at (name) put (typeNode.toGrace 0)", " name", " }", "}", "", "var seed := 100", "", "method sequenceNr {", " seed := seed + 1", " seed", "}", "", "method methodSignature(methNode) → String {", " var s: String := \"\"", " var shouldEmitTypeParams := methNode.hasTypeParams", " methNode.signatureParts.do { part →", " s := s ++ part.name", " if (shouldEmitTypeParams) then {", " s := s ++ methNode.typeParams.toGrace 1", " shouldEmitTypeParams := false // emit them once, after first part", " }", " if (part.params.isEmpty.not) then {", " s := s ++ \"(\"", " part.params.do { p →", " s := \"{s}{p.toGrace 1}:{p.decType.toGrace 1}\"", " } separatedBy {", " s := \"{s}, \"", " }", " s := s ++ \")\"", " }", " }", " \"{s} → {methNode.decType.toGrace 0}\"", "}", "", "method readerSignature(declNode) → String {", " \"{declNode.nameString} → {declNode.decType.toGrace 0}\"", "}", "", "method writerSignature(declNode) → String {", " \"{declNode.nameString}:=(_:{declNode.decType.toGrace 0}) → Done\"", "}", "", "def importedScopes = dictionary.empty", "", "method processGct(gct, importedModuleScope) {", " // Populates importedModuleScope with the information in gct,", " // which is a dictionary mapping gct keys to collections.", " // TODO: make the gct dictionary a real object.", "", " def moduleName = (ast.withoutLeadingComponents (gct.at \"path\".first)).", " replace \".grace\" with \"\"", " importedScopes.clear // because we will be importing multiple modules", " def moduleScopeId = gct.at \"self\".first", " def scopeKey = \"scope:{moduleScopeId}\"", " importedScopes.at (moduleScopeId) put (importedModuleScope)", " gct.at (scopeKey) ifAbsent {", " ProgrammingError.raise \"gct for \\\"{moduleName}\\\" missing \\\"{scopeKey}\\\" for the module itself\"", " }.do { gctLine →", " addGctLine (gctLine) toScope (importedModuleScope) for (gct)", " }", " gct.at \"freshScopes\".do { eachLine ->", " def elems = eachLine.split \" \"", " def eachScope = scopeWithUid(elems.first) for (gct)", " eachScope.isFresh := true", " if ((elems.size > 1) && {elems.second == \"trait\"}) then {", " eachScope.isTrait := true", " }", " }", "}", "", "method addGctLine (gctLine:String) toScope (s) for (gct) {", " // Adds a symbol table entry based on gctLine to scope s", " //", " // gctLine is generated by the method generateGctForModule, and has format", " // <methodName> <declaredType> <kindString> <attributeScope> <attributes>", " // where attributes is optional, and consists of a comma-separated list of strings", "", " def split = gctLine.split \" \"", " var newVar", " if (split.size == 2) then {", " def typeName = split.first", " newVar := sm.typeVariableFrom (", " constantScope.typeNode (typeName) params (numTypeParams(typeName)))", " } elseif { split.size ≥ 4 } then {", " def name = split.first", " def typeName = split.second", " def tag = split.third", " def scpdId = split.fourth", " newVar := sm.variable (tag) from (", " constantScope.pseudoNode (name) typed (typeName) scope (s).", " attributeScope (scopeWithUid(scpdId) for (gct)))", " if (split.size ≥ 5) then {", " def annNames = split.fifth", " newVar.annotationNames := annNames.split \",\"", " if (newVar.annotationNames.contains \"$fresh\") then {", " newVar.attributeScope.markAsFresh", " }", " }", " } else {", " EnvironmentException.raise \"gct line \\\"{gctLine}\\\" has wrong number of fields\"", " }", " s.add(newVar)", "}", "", "method numTypeParams(typeName) is confidential {", " // typeName can contain a parameter list, as in \"Dictonary⟦K,T⟧\"", "", " var ix := typeName.indexOf \"⟦\" ifAbsent { return 0 }", " var p := 1", " while { true } do {", " ix := typeName.indexOf \",\" startingAt (ix + 1) ifAbsent { return p }", " p := p + 1", " }", "}", "", "method scopeWithUid(str) for (gct) {", " // find the appropriate external scope, or create it if it", " // does not yet exist", "", " def result = importedScopes.at(str) ifAbsent {", " sm.predefined.at(str) ifAbsent {", " def newScope = sm.externalScope", " def scopeKey = \"scope:{str}\"", " importedScopes.at(str) put (newScope)", " gct.at (scopeKey) ifAbsent {", " def moduleName = (ast.withoutLeadingComponents (gct.at \"path\".first)).", " replace \".grace\" with \"\"", " ProgrammingError.raise \"gct for module \\\"{moduleName}\\\" does not contain \\\"{scopeKey}\\\"\"", " }.do { gctLine →", " addGctLine (gctLine) toScope (newScope) for (gct)", " }", " newScope", " }", " }", " result", "}", "", "method setupContext(moduleNode) {", " util.setPosition(0, 0)", "", " dialectScope.clear // so that resolve can be serially re-used.", " moduleScope.clear", " varFieldDecls.clear", "", " def dialectName:String = moduleNode.dialectName", " if (dialectName ≠ \"none\") then {", " xmodule.checkDialect(moduleNode)", " processGct(xmodule.gctDictionaryFor(dialectName), dialectScope)", " }", "}", "", "method checkTraitBody(traitObjNode) {", " traitObjNode.value.do { node →", " if (node.isLegalInTrait.not) then {", " def badThing = node.statementName", " def article = articleFor (badThing)", " errormessages.syntaxError(\"{article} {badThing} cannot appear in \" ++", " \"a trait (defined on line {traitObjNode.line})\")", " atLine(node.line)", " }", " }", "}", "", "method articleFor(str) {", " // the indefinite article to preceed str", " if (\"aeioAEIO\".contains(str.first)) then { \"an\" } else { \"a\" }", "}", "", "method buildSymbolTableFor(topNode) ancestors(topChain) {", " def symbolTableVis = object {", " inherit ast.baseVisitor", "", " method visitAssignment (o) up (anc) {", " o.scope := anc.parent.scope", " def lValue = o.dest", " if (lValue.isIdentifier) then {", " lValue.isAssigned := true", " }", " return true", " }", " method visitRequest (o) up (anc) {", " def enclosingNode = anc.parent", " def scope = enclosingNode.scope", " o.scope := scope", " def callee = o.receiver", " if (callee.isIdentifier) then {", " callee.inRequest := true", " }", " o.parts.do { each → each.scope := scope }", " if (enclosingNode.isMethod) then {", " if (enclosingNode.body.last == o) then {", " o.isTailCall := true", " }", " } elseif { enclosingNode.isReturn } then {", " o.isTailCall := true", " }", " return true", " }", " method visitBlock (o) up (anc) {", " o.scope := sm.blockScope.in(anc.parent.scope)", " true", " }", " method visitDefDec (o) up (anc) {", " def myParent = anc.parent", " def s = myParent.scope", " o.scope := s", " o.parentKind := myParent.kind", " def rhs = o.value", " def nameString = o.nameString", " if (rhs.isObject) then { rhs.name := nameString }", " if (myParent.isObject) then {", " if (o.isTyped) then {", " s.methodTypes.at(nameString) put(readerSignature(o))", " }", " }", " true", " }", " method visitVarDec (o) up (anc) {", " def myParent = anc.parent", " def s = myParent.scope", " o.scope := s", " o.parentKind := myParent.kind", " if (myParent.isObject) then {", " if (o.isTyped) then {", " s.methodTypes.at (o.nameString) put(readerSignature(o))", " s.methodTypes.at (o.writerNameString) put(writerSignature(o))", " }", " }", " true", " }", " method visitUniversalDec (o) up (anc) {", " def myParent = anc.parent", " def s = myParent.scope // the scope of the method parameters", " o.scope := s", " o.parentKind := myParent.kind // methodDec or methodtype (for a signature)", " true // hope that visitIdentifier creates the variable", " }", " method visitIdentifier (o) up (anc) {", " var scope := anc.parent.scope", " o.scope := scope", " def isWild = o.wildcard", " if (o.isBindingOccurrence) then {", " if (o.isDeclaredByParent.not && isWild.not) then {", " def declaringNode = o.declaringNodeWithAncestors(anc)", " if (scope.isObjectScope && declaringNode.isVarDec) then {", " scope.add(sm.varVariableFrom(declaringNode)) withName (o.writerNameString)", " // scope.add will complain if o.writerNameString is already declared.", " // We use a variableVar and not a variableMethod to", " // distinguish this from a hand-written assignment method", " }", " scope.add(declaringNode.createVariableFor(o))", " }", " } elseif {isWild} then {", " errormessages.syntaxError(\"'_' cannot be used in an expression\")", " atRange(o.range)", " }", " true", " }", " method visitAlias (o) up (ac) {", " o.scope := ac.parent.scope", " o.newSignature.isDeclaredByParent := true", " o.newName.accept(self) from (ac.extend(o))", " false // no need to visit the aliasNode's other components", " }", " method visitImport (o) up (anc) {", " o.scope := anc.parent.scope", " xmodule.checkExternalModule(o)", " def gct = xmodule.gctDictionaryFor(o.moduleName)", " def importedScope = sm.externalScope", " importedScope.node := o", " processGct(gct, importedScope)", " o.scope.add(sm.importVariableFrom(o).attributeScope(importedScope))", " withName(o.nameString)", " o.name.isDeclaredByParent := true", " // to prevent redeclaration when we visit the identifier", " true", " }", " method visitInherit (o) up (anc) {", " o.scope := anc.parent.scope", " if (o.isUse) then {", " if (anc.parent.canUse.not) then {", " errormessages.syntaxError(\"use statements must \" ++", " \"be inside an object, class, or trait\")", " atRange(o.range)", " }", " } else {", " if (anc.parent.canInherit.not) then {", " errormessages.syntaxError(\"inherit statements must \" ++", " \"be inside an object or class; a trait cannot inherit\")", " atRange(o.range)", " }", " }", " true", " }", " method visitMethodDec (o) up (anc) {", " def surroundingScope = anc.parent.scope", " if (surroundingScope.isObjectScope.not) then {", " // The parser accepts method declarations as statments, and thus", " // class and trait declarations as statements too.", " // Here we check that they are inside an object.", " // This produces better diagnostics than rejecting them in", " // the parser, as well as simplifying the parser.", "", " errormessages.syntaxError(\"{o.description} declarations are \" ++", " \"permitted only inside an object\") atRange(o.range)", " }", " def ident = o.asIdentifier", " if (ident.isBindingOccurrence) then {", " ident.isDeclaredByParent := true", " // aliased and excluded names are appliedOccurrences", " o.scope := sm.methodScope.in(surroundingScope)", " surroundingScope.add(o.createVariableFor(ident))", " if (o.isPublic) then {", " if (o.isTyped) then {", " surroundingScope.methodTypes.at(ident.nameString) put(methodSignature(o))", " }", " }", " }", " if (o.returnsObject) then {", " o.returnedObject.name := o.canonicalName", " }", " true", " }", " method visitMethodSignature (o) up (anc) {", " def surroundingScope = anc.parent.scope", " if (o.isAppliedOccurrence) then { // on rhs of an alias, or in an exclude", " o.scope := surroundingScope", " return true", " }", " def ident = o.asIdentifier", " if (ident.isDeclaredByParent.not) then {", " surroundingScope.add(sm.methodVariableFrom (o))", " ident.isDeclaredByParent := true", " }", " o.scope := sm.parameterScope.in(anc.parent.scope)", " // the scope for the parameters (including the type parameters,", " // if any) of this method.", " true", " }", " method visitObject (o) up (anc) {", " def myParent = anc.parent", " o.scope := sm.objectScope.in(myParent.scope)", " if (o.inTrait) then { checkTraitBody(o) }", " true", " }", " method visitModule(o) up (anc) {", " // the module scope was set before the traversal started", " true", " }", " method visitTypeDec (o) up (anc) {", " def enclosingScope = anc.parent.scope", " if (enclosingScope.isObjectScope.not) then {", " errormessages.syntaxError(\"type declarations are permitted only\" ++", " \" inside an object\") atRange(o.range)", " }", " def ident = o.name", " enclosingScope.add(sm.typeVariableFrom(o))", " enclosingScope.types.at(ident.nameString) put(o.toGrace 0)", " ident.isDeclaredByParent := true", " o.scope := sm.typeScope.in(enclosingScope)", " // this scope will be the home for any type parameters.", " // If there are no parameters, it won't be used.", " true", " }", " method visitInterfaceLiteral (o) up (anc) {", " o.scope := sm.interfaceScope.in(anc.parent.scope)", " true", " }", " method visitReturn(o) up (anc) {", " o.scope := anc.parent.scope;", " def enclosingMethodNode = anc.suchThat { n → n.isMethod } ifAbsent {", " errormessages.syntaxError \"`return` statements must be inside methods.\"", " atRange(o.range)", " }", " o.dtype := enclosingMethodNode.dtype", " true", " }", " method visitYourself(o) up (anc) {", " def currentScope = anc.parent.scope", " o.scope := currentScope", " def nodeObjects = list []", " o.theObjects := nodeObjects", " var currentObjectScope := currentScope.currentObjectScope", " repeat (o.numberOfLevels) times {", " nodeObjects.addLast(currentObjectScope.node)", " currentObjectScope := currentObjectScope.enclosingObjectScope", " }", " true", " }", " method visitTypeParameters(o) up (anc) { o.scope := anc.parent.scope ; true }", " method visitIf(o) up (anc) { o.scope := anc.parent.scope ; true }", " method visitMatchCase(o) up (anc) { o.scope := anc.parent.scope ; true }", " method visitTryCatch(o) up (anc) { o.scope := anc.parent.scope ; true }", " method visitSignaturePart(o) up (anc) { o.scope := anc.parent.scope ; true }", " method visitSequence(o) up (anc) { o.scope := anc.parent.scope ; true }", " method visitRequestWithoutArgs(o) up (anc) {", " visitRequest(o) up (anc)", " }", " method visitTypeApplication(o) up (anc) { o.scope := anc.parent.scope ; true }", " method visitString(o) up (anc) { o.scope := anc.parent.scope ; true }", " method visitNumeral(o) up (anc) { o.scope := anc.parent.scope ; true }", " method visitOp(o) up (anc) { o.scope := anc.parent.scope ; true }", " method visitDialect(o) up (anc) { o.scope := anc.parent.scope ; true }", " method visitCommentNode(o) up (anc) { o.scope := anc.parent.scope ; true }", " method visitEllipsis(o) up (anc) { o.scope := anc.parent.scope ; true }", " } // end of symbolTableVis", "", " def currentObjectScopesVis = object {", " // Puts the scope of returned objects into the symbol table and", " // marks variables as being Fresh", "", " // This traversal can't be completed in the buildSymbolTable visitor,", " // because the visitation is top-down, and hence the scope of the", " // body of a def or method won't have been allocated when the", " // declaration is visited.", "", " inherit ast.baseVisitor", "", " method noEarlyReturn(methNode) {", " def erv = earlyReturnVis", " methNode.accept(erv)", " erv.containsEarlyReturn.not", " }", " method visitMethodDec (o) up (anc) {", " def myParent = anc.parent", " def surroundingScope = myParent.scope", " if (o.returnsObject) then {", " if (anc.forebears.forebears.isEmpty.not) then {", " // prefixes a dotted name to the name of the returned object", " // --- but not if I'm at the module-level", " def factoryName = myParent.name", " def tailNode = o.returnedObject", " if ((factoryName != \"object\") && (tailNode.isObject)) then {", " tailNode.name := factoryName ++ \".\" ++ tailNode.name", " }", " }", " if (o.isOnceMethod.not) then {", " if (noEarlyReturn(o)) then {", " o.isFresh := true", " def methodVariable = surroundingScope.lookup(o.nameString)", " methodVariable.isFresh := true", " o.returnedObjectScope.isFresh := true // TODO — is this right?", " }", " }", " }", " true", " }", " }", "", " def inheritanceVis = object {", " inherit ast.baseVisitor", " method visitObject (o) up (anc) {", " collectReusedNames(o)", " true", " }", " method visitModule (o) up (anc) {", " collectReusedNames(o)", " true", " }", " }", "", " topNode.accept(symbolTableVis) from(topChain)", " topNode.accept(currentObjectScopesVis) from(topChain)", " topNode.accept(inheritanceVis) from(topChain)", "}", "", "class earlyReturnVis {", " inherit ast.baseVisitor", " var containsEarlyReturn is readable := false", " method visitReturn(o) {", " containsEarlyReturn := true", " false // stop visitattion", " }", " method visitObject(o) {", " false // stop visitation", " }", "}", "", "method collectReusedNames(node) is confidential {", " // node is an object or class; puts the names that it inherits and uses into", " // its scope. In the process, checks for a cycle in the inheritance chain", " def nodeScope = node.scope", " if (nodeScope.areReusedNamesCompleted) then {", " return", " }", " if (nodeScope.areReusedNamesInProgress) then {", " errormessages.syntaxError \"cyclic inheritance or trait use.\"", " atRange(node.line, node.column, node.column + 4)", " }", " nodeScope.markReusedNamesAsInProgress", " gatherInheritedNames(node)", " gatherUsedNames(node)", " nodeScope.markReusedNamesAsCompleted", "}", "", "method gatherInheritedNames(node) is confidential {", " if (node.isObject) then {", " var inhNode := node.superclass", " def objScope = node.scope", " var superScope", " if (false == inhNode) then {", " def gO = ast.identifier(\"graceObject\", false).setScope (objScope)", " inhNode := ast.inheritStatement(gO).setScope (objScope)", " superScope := constantScope.objectScope", " } else {", " superScope := scopeReferencedByReuseExpr(inhNode.value)", " inhNode.reusedScope := superScope", " if (superScope.isExternal.not) then { collectReusedNames(superScope.node) }", " }", " def excludedNames = inhNode.exclusions.map { exMeth → exMeth.nameString } >> list", " superScope.localAndReusedNamesAndValuesDo { name, defn →", " if ((name ≠ \"self\") && (excludedNames.contains(name).not)) then {", " objScope.addReused(defn) withName (name)", " }", " }", " inhNode.aliases.do { a →", " def old = a.oldName.nameString", " def new = a.newName.nameString", " def defn = superScope.lookupLocallyOrReused(old) ifAbsent {", " errormessages.syntaxError(\"can't define an alias for \" ++", " a.oldName.canonicalName ++", " \" because it is not present in the inherited object\")", " atRange(a.oldName.range)", " }", " objScope.add (sm.aliasMethodVariableFrom(a) to (defn)) withName (new)", " // An alias is added as a local method, not as a reused method", " }", " inhNode.exclusions.do { exMeth →", " if (superScope.definesLocallyOrReuses(exMeth.nameString).not) then {", " errormessages.syntaxError(\"can't exclude {exMeth.canonicalName} \" ++", " \"because it is not present in the inherited object\")", " atRange(exMeth.range)", " }", " }", " }", "}", "", "method gatherUsedNames(objNode) is confidential {", " // For each of objNodes's used traits, gather the names", " // introduced by that trait, as modified by alias and exclude.", "", " def traitMethods = dictionary.empty", " // maps method names to the trait(s) that provide(s) them - for detecting conflicts", " def objScope = objNode.scope", " objNode.usedTraits.do { t ->", " def traitScope = scopeReferencedByReuseExpr(t.value)", " util.log 46 verbose \"gather