def generateSetExec(s, m, loc, prefix, target): if not target: return Error(loc, u"Missing target to import") if prefix: if type(target[0]) == reader.SymbolExp: if target[ 0].isAtom: # FIXME: This check should occur even if prefix does not return Error(target[0].loc, u"Expected a symbol after \"import\"") newSymbol = reader.SymbolExp(target[0].loc, True) newSymbol.content = target[0].content target = [newSymbol] + target[1:] target = prefix + target if len(target) == 1: return Error( target[0].loc, u"import expects either multiple symbols or a \"from\" clause") if type(target[-1]) != reader.SymbolExp or not target[-1].isAtom: return Error(target[-1].loc, u"End of import path needs to be an atom") symbol = execution.AtomLiteralExec(target[-1].loc, target[-1].content) return execution.SetExec(loc, True, False, False, False, None, symbol, m.process(target))
def apply(s, m, left, node, right, _): export = False if left: if not (len(left) == 1 and isSymbol(left[0], "export")): return Error(node.loc, "Stray garbage before \"%s\"" % s.symbol()) export = True if not right: return Error(node.loc, u"Emptiness after \"%s\"" % s.symbol()) macroGroup = right[0] if type(macroGroup) == reader.SymbolExp: # TODO: Consider only allowing this if atom keys. TODO: Do something more sensible when this fails? macroObject = m.process(right).eval(execution.profileScope) try: macroList = macroObject.apply( execution.AtomLiteralExec(node.loc, execution.macroExportList)) except execution.InternalExecutionException as e: raise execution.ExecutionException(macroGroup.loc, u"macro load", unicode(e)) if type(macroList) != list: return Error( macroGroup.loc, u"macro import path did not resolve to a valid module") else: payload = None importObject = macroObject if isinstance(importObject, execution.LazyMacroLoader ): # TODO: What about module objects? importObject = importObject.importObject() if importObject: payload = execution.ImportAllExec( node.loc, execution.StoredLiteralExec(node.loc, importObject), export) return ([], UserMacroList(node.loc, macroList, export, s.profile, payload), []) elif type(macroGroup) == reader.ExpGroup: if len(right) > 1: return Error( node.loc, u"Stray garbage after \"%s (group)\"" % s.symbol()) macros = m.makeArray(macroGroup) return ([], UserMacroList( node.loc, [ast.eval(execution.defaultScope) for ast in macros], export, s.profile), []) else: return Error( node.loc, u"Expected a path or a (group) after \"%s\"" % s.symbol())
def apply(s, m, left, node, right, _): for case in switch(type(node)): if case(reader.QuoteExp): node = execution.StringLiteralExec(node.loc, node.content) elif case(reader.NumberExp): value = node.integer if node.dot: value += "." if node.decimal is not None: value += node.decimal node = execution.NumberLiteralExec(node.loc, float(value)) elif case(reader.SymbolExp): if node.isAtom: node = execution.AtomLiteralExec(node.loc, node.content) else: node = execution.VarExec(node.loc, node.content) else: return Error( node.loc, "Internal error: AST node of indecipherable type %s found in a place that shouldn't be possible" % (type(node).__name__)) return (left, node, right)
def apply(s, m, left, node, right, tracker): isLet = False isMethod = False isField = False isExport = False target = None for idx in range(len(left)): if isSymbol(left[idx], u"let"): isLet = True elif isSymbol(left[idx], u"method"): isMethod = True elif isSymbol(left[idx], u"field"): isField = True elif isSymbol(left[idx], u"export"): isExport = True else: break if isLet and isExport: return Error(node.loc, "Cannot use \"let\" and \"export\" together") if left: left = left[idx:] if len(left) == 0: return Error(node.loc, "Missing name in =") key = left[-1] if len(left) > 1: target = m.process(left[:-1]) key = m.process([key]) else: # Currently under all circumstances a = b is a flat atom assignment if type(key) != reader.SymbolExp or key.isAtom: return Error(key.loc, "Assigned name must be alphanumeric") key = execution.AtomLiteralExec(key.loc, key.content) value = m.process(right, tracker) return ([], execution.SetExec(node.loc, isLet, isMethod, isField, isExport, target, key, value), [])
def apply(s, m, left, node, right, tracker): if not right: return Error(node.loc, u"Emptiness after \"match\"") lines = right.pop(0) if type(lines) != reader.ExpGroup: return Error(node.loc, u"Expected a (group) after \"match\"") result = [] for stmIdx in range(len(lines.statements) if lines.statements else 0): stm = lines.statements[stmIdx] if not stm.nodes: # Match is "like code" so may contain a blank line...? continue eqIdx = None # Find = sign for idx in range(len(stm.nodes)): if isSymbol(stm.nodes[idx], '='): eqIdx = idx break if eqIdx is None: return Error( node.loc, u"match line #%d does not have an =" % (stmIdx + 1)) eqNode = stm.nodes[eqIdx] eqLeft = stm.nodes[:eqIdx] eqRight = stm.nodes[eqIdx + 1:] if not eqLeft: return Error( node.loc, u"On match line #%d, left of = is blank" % (stmIdx + 1)) if len(eqLeft) > 2: return Error( node.loc, u"On match line #%d, left of = has too many symbols. Try adding parenthesis?" % (stmIdx + 1)) if not eqRight: return Error( node.loc, u"On match line #%d, right of = is blank" % (stmIdx + 1)) target = eqLeft.pop(0) unpacksExp = None unpacks = [] if eqLeft: unpacksExp = eqLeft[0] foundUnpack = False if type(unpacksExp) == reader.SymbolExp: unpacks = [ execution.AtomLiteralExec(unpacksExp.loc, unpacksExp.content) ] foundUnpack = True elif type(unpacksExp) == reader.ExpGroup: for statement in unpacksExp.statements: if not statement.nodes or type( statement.nodes[0]) != reader.SymbolExp: foundUnpack = False break unpacks.append( execution.AtomLiteralExec( statement.nodes[0].loc, statement.nodes[0].content)) foundUnpack = True if not foundUnpack: return Error( node.loc, u"On match line #%d, variable unpack list on left of = is garbled" % (stmIdx + 1)) if isSymbol(target, '_'): if unpacksExp: return Error( node.loc, u"On match line #%d, variable unpack list used with _" % (stmIdx + 1)) target = None elif isSymbol(target, 'array'): if not unpacksExp: return Error( node.loc, u"On match line #%d, \"array\" used but no unpack list found" % (stmIdx + 1)) target = None if target: target = m.process([target]) tempStatement = m.process(eqRight, tracker) result.append(MatchCase(target, unpacks, tempStatement)) return (left, execution.MakeMatchExec(node.loc, result), right)