Mercurial > lcfOS
annotate python/ppci/c3/builder.py @ 366:39bf68bf1891
Fix sample tests and deterministic build
author | Windel Bouwman |
---|---|
date | Fri, 21 Mar 2014 09:43:01 +0100 |
parents | 5477e499b039 |
children | fb3c1f029b30 |
rev | line source |
---|---|
254 | 1 import logging |
306 | 2 from .lexer import Lexer |
300 | 3 from .parser import Parser |
4 from .codegenerator import CodeGenerator | |
308 | 5 from .scope import createTopScope, Scope |
6 from .visitor import AstPrinter, Visitor | |
7 from .astnodes import Package, Function, Identifier, Symbol | |
8 | |
9 | |
10 class C3Pass: | |
11 def __init__(self, diag): | |
12 self.diag = diag | |
13 self.logger = logging.getLogger('c3') | |
14 self.visitor = Visitor() | |
15 | |
16 def error(self, msg, loc=None): | |
17 self.pkg.ok = False | |
18 self.diag.error(msg, loc) | |
19 | |
20 def visit(self, pkg, pre, post): | |
21 self.visitor.visit(pkg, pre, post) | |
22 | |
23 | |
24 class ScopeFiller(C3Pass): | |
25 scoped_types = [Package, Function] | |
26 | |
27 def __init__(self, diag, topScope, packages): | |
28 super().__init__(diag) | |
29 self.topScope = topScope | |
30 self.packages = packages | |
31 | |
32 """ Scope is attached to the correct modules. """ | |
33 def addScope(self, pkg): | |
334 | 34 self.logger.debug('Adding scoping to package {}'.format(pkg.name)) |
308 | 35 self.pkg = pkg |
36 # Prepare top level scope and set scope to all objects: | |
37 self.scopeStack = [self.topScope] | |
38 modScope = Scope(self.CurrentScope) | |
39 self.scopeStack.append(modScope) | |
40 self.visit(pkg, self.enterScope, self.quitScope) | |
41 assert len(self.scopeStack) == 2 | |
42 | |
334 | 43 self.logger.debug('Resolving imports for package {}'.format(pkg.name)) |
308 | 44 # Handle imports: |
45 for i in pkg.imports: | |
46 if i not in self.packages: | |
47 self.error('Cannot import {}'.format(i)) | |
48 continue | |
49 pkg.scope.addSymbol(self.packages[i]) | |
50 | |
51 @property | |
52 def CurrentScope(self): | |
53 return self.scopeStack[-1] | |
54 | |
55 def addSymbol(self, sym): | |
56 if self.CurrentScope.hasSymbol(sym.name): | |
57 self.error('Redefinition of {0}'.format(sym.name), sym.loc) | |
58 else: | |
59 self.CurrentScope.addSymbol(sym) | |
60 | |
61 def enterScope(self, sym): | |
62 # Attach scope to references: | |
63 if type(sym) is Identifier: | |
64 sym.scope = self.CurrentScope | |
65 | |
66 # Add symbols to current scope: | |
67 if isinstance(sym, Symbol): | |
68 self.addSymbol(sym) | |
69 sym.scope = self.CurrentScope | |
70 | |
71 # Create subscope for items creating a scope: | |
72 if type(sym) in self.scoped_types: | |
73 newScope = Scope(self.CurrentScope) | |
74 self.scopeStack.append(newScope) | |
75 sym.innerScope = self.CurrentScope | |
76 | |
77 def quitScope(self, sym): | |
78 # Pop out of scope: | |
79 if type(sym) in self.scoped_types: | |
80 self.scopeStack.pop(-1) | |
165 | 81 |
287 | 82 |
165 | 83 class Builder: |
288 | 84 """ |
186 | 85 Generates IR-code from c3 source. |
300 | 86 Reports errors to the diagnostics system. |
186 | 87 """ |
301 | 88 def __init__(self, diag, target): |
254 | 89 self.logger = logging.getLogger('c3') |
226 | 90 self.diag = diag |
306 | 91 self.lexer = Lexer(diag) |
226 | 92 self.parser = Parser(diag) |
307 | 93 self.cg = CodeGenerator(diag) |
306 | 94 self.topScope = createTopScope(target) # Scope with built in types |
194 | 95 |
287 | 96 def build(self, srcs, imps=[]): |
251
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
226
diff
changeset
|
97 """ Create IR-code from sources """ |
334 | 98 self.logger.debug('Building {} source files'.format(len(srcs))) |
306 | 99 iter(srcs) # Check if srcs are iterable |
100 iter(imps) | |
288 | 101 self.ok = True |
306 | 102 self.pkgs = {} |
103 | |
307 | 104 # Parsing stage (phase 1) |
306 | 105 def doParse(src): |
106 tokens = self.lexer.lex(src) | |
107 return self.parser.parseSource(tokens) | |
366 | 108 s_pkgs = list(map(doParse, srcs)) |
109 i_pkgs = list(map(doParse, imps)) | |
110 all_pkgs = s_pkgs + i_pkgs | |
306 | 111 if not all(all_pkgs): |
112 self.ok = False | |
113 return | |
114 | |
307 | 115 # Fix scopes and package refs (phase 1.5) |
306 | 116 packages = {pkg.name: pkg for pkg in all_pkgs} |
117 self.pkgs = packages | |
307 | 118 |
119 scopeFiller = ScopeFiller(self.diag, self.topScope, packages) | |
306 | 120 # Fix scopes: |
121 for pkg in all_pkgs: | |
307 | 122 scopeFiller.addScope(pkg) |
306 | 123 if not all(pkg.ok for pkg in all_pkgs): |
124 self.ok = False | |
125 return | |
126 | |
307 | 127 # Generate intermediate code (phase 2) |
128 # Only return ircode when everything is OK | |
366 | 129 for pkg in s_pkgs: |
307 | 130 yield self.cg.gencode(pkg) |
306 | 131 if not all(pkg.ok for pkg in all_pkgs): |
132 self.ok = False |