changeset 251:6ed3d3a82a63

Added another c3 example. First import attempt
author Windel Bouwman
date Mon, 29 Jul 2013 20:23:13 +0200
parents f5fba5b554d7
children c4370696ccc7
files python/c3/analyse.py python/c3/astnodes.py python/c3/builder.py python/c3/examples/functions.c3 python/c3/parser.py python/cortexm3.py python/hexfile.py python/ide.py python/ppci/errors.py python/stm32f4/blink.c3 python/stm32f4/burn.c3 python/stm32f4/stm32f4xx.c3 python/testasm.py python/testc3.py python/testhexfile.py
diffstat 15 files changed, 179 insertions(+), 103 deletions(-) [+]
line wrap: on
line diff
--- a/python/c3/analyse.py	Sun Jul 28 19:07:51 2013 +0200
+++ b/python/c3/analyse.py	Mon Jul 29 20:23:13 2013 +0200
@@ -12,13 +12,24 @@
     def __init__(self, diag):
         self.diag = diag
 
-    def analyzePackage(self, pkg):
+    def analyzePackage(self, pkg, packageProvider):
         self.ok = True
         visitor = Visitor()
         # Prepare top level scope:
         self.scopeStack = [topScope]
+        modScope = Scope(self.CurrentScope)
+        self.scopeStack.append(modScope)
         visitor.visit(pkg, self.enterScope, self.quitScope)
         del self.scopeStack
+
+        # Handle imports:
+        for i in pkg.imports:
+            ip = packageProvider.getPackage(i)
+            if not ip:
+                self.error('Cannot import {}'.format(i))
+                continue
+            for x in ip.declarations:
+                modScope.addSymbol(x)
         visitor.visit(pkg, self.findRefs)
         visitor.visit(pkg, self.sanity)
         return self.ok
@@ -28,31 +39,29 @@
         self.diag.error(msg, loc)
 
     @property
-    def currentScope(self):
+    def CurrentScope(self):
         return self.scopeStack[-1]
 
     # Scope creation:
     def addSymbol(self, sym):
-        if self.currentScope.hasSymbol(sym.name):
+        if self.CurrentScope.hasSymbol(sym.name):
             self.error('Redefinition of {0}'.format(sym.name), sym.loc)
         else:
-            self.currentScope.addSymbol(sym)
+            self.CurrentScope.addSymbol(sym)
 
     def enterScope(self, sym):
         # Distribute the scope:
-        sym.scope = self.currentScope
+        sym.scope = self.CurrentScope
 
         # Add symbols to current scope:
-        if isinstance(sym, Symbol):
-            self.addSymbol(sym)
-        if isinstance(sym, DefinedType):
+        if isinstance(sym, Symbol) or isinstance(sym, DefinedType):
             self.addSymbol(sym)
 
         # Create subscope:
         if type(sym) in [Package, Function]:
-            newScope = Scope(self.currentScope)
+            newScope = Scope(self.CurrentScope)
             self.scopeStack.append(newScope)
-            sym.innerScope = self.currentScope
+            sym.innerScope = self.CurrentScope
 
     def quitScope(self, sym):
         # Pop out of scope:
--- a/python/c3/astnodes.py	Sun Jul 28 19:07:51 2013 +0200
+++ b/python/c3/astnodes.py	Mon Jul 29 20:23:13 2013 +0200
@@ -16,6 +16,7 @@
         self.name = name
         self.loc = loc
         self.declarations = []
+        self.imports = []
     def __repr__(self):
         return 'PACKAGE {}'.format(self.name)
 
--- a/python/c3/builder.py	Sun Jul 28 19:07:51 2013 +0200
+++ b/python/c3/builder.py	Mon Jul 29 20:23:13 2013 +0200
@@ -1,6 +1,7 @@
 import ppci
 from . import Parser, TypeChecker, Analyzer, CodeGenerator
 from . astprinter import AstPrinter
+import glob
 
 class Builder:
     """ 
@@ -13,19 +14,43 @@
         self.tc = TypeChecker(diag)
         self.al = Analyzer(diag)
         self.cg = CodeGenerator()
-    def build(self, src):
-        """ Create IR-code from sources """
+        self.packages = {}
+
+    def getPackage(self, pname):
+        """ package provider for use when analyzing """
+        if pname in self.packages:
+            return self.packages[pname]
+        else:
+            # Try to lookup package from file
+            fns = glob.glob('./*/{}.c3'.format(pname))
+            if fns:
+                with open(fns[0]) as f:
+                    src = f.read()
+                self.build(src)
+            if pname in self.packages:
+                return self.packages[pname]
+
+    def parse(self, src):
         pkg = self.parser.parseSource(src)
         if not pkg:
             return
-        self.pkg = pkg
+
         # TODO: merge the two below?
         #AstPrinter().printAst(pkg)
-        if not self.al.analyzePackage(pkg):
+        if not self.al.analyzePackage(pkg, self):
             return
         if not self.tc.checkPackage(pkg):
             return
 
+        # Store for later use:
+        self.packages[pkg.name] = pkg
+        return pkg
+
+    def build(self, src):
+        """ Create IR-code from sources """
+        pkg = self.parse(src)
+
         # Only return ircode when everything is OK
-        return self.cg.gencode(pkg)
+        if pkg:
+            return self.cg.gencode(pkg)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/c3/examples/functions.c3	Mon Jul 29 20:23:13 2013 +0200
@@ -0,0 +1,27 @@
+
+/*
+ Demo of function usage
+*/
+
+package functiondemo;
+
+function void main()
+{
+    var int a, b, c;
+    a = 3;
+    b = a;
+    a =3;
+    b = fib(a + 9);
+    sum(a, b);
+}
+
+function int fib(int x)
+{
+    return fib(x - 1) * x;
+}
+
+function int sum(int a, int b)
+{
+    return a + b;
+}
+
--- a/python/c3/parser.py	Sun Jul 28 19:07:51 2013 +0200
+++ b/python/c3/parser.py	Mon Jul 29 20:23:13 2013 +0200
@@ -51,9 +51,11 @@
     def addDeclaration(self, decl):
         self.currentPart.declarations.append(decl)
     
-    def parseUses(self):
-        # TODO: parse uses
-        pass
+    def parseImport(self):
+        self.Consume('import')
+        name = self.Consume('ID').val
+        self.mod.imports.append(name)
+        self.Consume(';')
 
     def parsePackage(self):
         self.Consume('package')
@@ -61,22 +63,23 @@
         self.Consume(';')
         self.mod = astnodes.Package(name.val, name.loc)
         self.currentPart = self.mod
-        self.parseUses()
         while self.Peak != 'END':
             self.parseTopLevel()
         self.Consume('END')
 
     def parseTopLevel(self):
-      if self.Peak == 'function':
-         self.parseFunctionDef()
-      elif self.Peak == 'var':
-         self.parseVarDef()
-      elif self.Peak == 'const':
-         self.parseConstDef()
-      elif self.Peak == 'type':
-         self.parseTypeDef()
-      else:
-         self.Error('Expected function, var, const or type')
+        if self.Peak == 'function':
+            self.parseFunctionDef()
+        elif self.Peak == 'var':
+            self.parseVarDef()
+        elif self.Peak == 'const':
+            self.parseConstDef()
+        elif self.Peak == 'type':
+            self.parseTypeDef()
+        elif self.Peak == 'import':
+            self.parseImport()
+        else:
+            self.Error('Expected function, var, const or type')
 
     def parseDesignator(self):
         """ A designator designates an object """
--- a/python/cortexm3.py	Sun Jul 28 19:07:51 2013 +0200
+++ b/python/cortexm3.py	Mon Jul 29 20:23:13 2013 +0200
@@ -487,6 +487,20 @@
         h = (0b11100 << 11) | imm11 # | 1 # 1 to enable thumb mode
         return u16(h)
 
+@armtarget.instruction
+class bl_ins(jumpBase_ins):
+    mnemonic = 'BL'
+    def encode(self):
+        imm32 = wrap_negative(self.offset >> 1, 32)
+        imm11 = imm32 & 0x7FF
+        imm10 = (imm32 >> 11) & 0x3FF
+        j1 = 1 # TODO: what do these mean?
+        j2 = 1
+        s = (imm32 >> 24) & 0x1
+        h1 = (0b11110 << 11) | (s << 10) | imm10 
+        h2 = (0b1101 << 12) | (j1 << 13) | (j2 << 11) | imm11
+        return u16(h1) + u16(h2)
+
 class cond_base_ins(jumpBase_ins):
     def encode(self):
         imm8 = wrap_negative(self.offset >> 1, 8)
--- a/python/hexfile.py	Sun Jul 28 19:07:51 2013 +0200
+++ b/python/hexfile.py	Mon Jul 29 20:23:13 2013 +0200
@@ -102,10 +102,6 @@
 
     def check(self):
         self.regions.sort(key=lambda r: r.address)
-        if len(self.regions) > 1:
-            for r1, r2 in zip(self.regions[:-1], self.regions[1:]):
-                if r1.EndAddress > r2.address:
-                    raise HexFileException('Overlapping regions')
         change = True
         while change and len(self.regions) > 1:
             change = False
@@ -114,6 +110,8 @@
                     r1.addData(r2.data)
                     self.regions.remove(r2)
                     change = True
+                elif r1.EndAddress > r2.address:
+                    raise HexFileException('Overlapping regions')
 
     def merge(self, other):
         for r in other.regions:
--- a/python/ide.py	Sun Jul 28 19:07:51 2013 +0200
+++ b/python/ide.py	Mon Jul 29 20:23:13 2013 +0200
@@ -257,15 +257,14 @@
             return
         self.diag.clear()
         self.buildOutput.append('Starting parse')
-        ir = self.c3front.build(ce.Source)
+        pkg = self.c3front.parse(ce.Source)
 
         # Set errors:
         for err in self.diag.diags:
             self.buildOutput.append(str(err))
         self.builderrors.setErrorList(self.diag.diags)
         ce.setErrors(self.diag.diags)
-        ast = self.c3front.pkg
-        self.astViewer.setAst(ast)
+        self.astViewer.setAst(pkg)
         self.buildOutput.append("Done!")
 
     def buildFile(self):
--- a/python/ppci/errors.py	Sun Jul 28 19:07:51 2013 +0200
+++ b/python/ppci/errors.py	Mon Jul 29 20:23:13 2013 +0200
@@ -14,7 +14,7 @@
             self.row = loc.row
             self.col = loc.col
         else:
-            self.row = self.col = None
+            self.row = self.col = 0
 
     def __repr__(self):
         if self.row:
@@ -23,11 +23,11 @@
             return 'Compilererror: "{0}"'.format(self.msg)
 
 def printError(source, e):
-     def printLine(row, txt):
+    def printLine(row, txt):
         print(str(row)+':'+txt)
-     if e.loc.row == 0:
-        print('Error: {0}'.format(e.msg))
-     else:
+    if e.row == 0:
+            print('Error: {0}'.format(e.msg))
+    else:
         lines = source.split('\n')
         ro, co = e.row, e.col
         prerow = ro - 2
--- a/python/stm32f4/blink.c3	Sun Jul 28 19:07:51 2013 +0200
+++ b/python/stm32f4/blink.c3	Mon Jul 29 20:23:13 2013 +0200
@@ -6,34 +6,7 @@
 
 package blink;
 
-type struct {
-    int MODER;
-    int OTYPER;
-    int OSPEEDR;
-    int PUPDR;
-    int IDR;
-    int ODR;
-}* GPIO_Type;
-
-type struct {
-    int CR;
-    int PLLCFGR;
-    int CFGR;
-    int CIR;
-    int AHB1RSTR;
-    int AHB2RSTR;
-    int AHB3RSTR;
-    int reserved0;
-    int APB1RSTR;
-    int APB2RSTR;
-    int reserved1a, reserved1b;
-    int AHB1ENR;
-    int AHB2ENR;
-    int AHB3ENR;
-    int reserved2;
-    int APB1ENR, APB2ENR;
-}* RCC_Type;
-
+import stm32f4xx;
 
 // Functions:
 function void main()
--- a/python/stm32f4/burn.c3	Sun Jul 28 19:07:51 2013 +0200
+++ b/python/stm32f4/burn.c3	Mon Jul 29 20:23:13 2013 +0200
@@ -6,48 +6,25 @@
 
 */
 
-package blink;
+package burn;
 
-type struct {
-    int MODER;
-    int OTYPER;
-    int OSPEEDR;
-    int PUPDR;
-    int IDR;
-    int ODR;
-}* GPIO_Type;
+import stm32f4xx;
 
-type struct {
-    int CR;
-    int PLLCFGR;
-    int CFGR;
-    int CIR;
-    int AHB1RSTR;
-    int AHB2RSTR;
-    int AHB3RSTR;
-    int reserved0;
-    int APB1RSTR;
-    int APB2RSTR;
-    int reserved1a, reserved1b;
-    int AHB1ENR;
-    int AHB2ENR;
-    int AHB3ENR;
-    int reserved2;
-    int APB1ENR, APB2ENR;
-}* RCC_Type;
+function void init()
+{
+}
 
-
-// Functions:
 function void main()
 {
-    // Memory mapped control registers:
-    var GPIO_Type GPIOD;
-    GPIOD = cast<GPIO_Type>(0x40020C00);
+    //init();
     var RCC_Type RCC;
     RCC = cast<RCC_Type>(0x40023800);
 
     // Enable the clock to port D:
     RCC->AHB1ENR = RCC->AHB1ENR | (1 << 3);
+    // Memory mapped control registers:
+    var GPIO_Type GPIOD;
+    GPIOD = cast<GPIO_Type>(0x40020C00);
 
     var int pin;
     pin = 15;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/stm32f4/stm32f4xx.c3	Mon Jul 29 20:23:13 2013 +0200
@@ -0,0 +1,31 @@
+
+package stm32f4xx;
+
+type struct {
+    int MODER;
+    int OTYPER;
+    int OSPEEDR;
+    int PUPDR;
+    int IDR;
+    int ODR;
+}* GPIO_Type;
+
+type struct {
+    int CR;
+    int PLLCFGR;
+    int CFGR;
+    int CIR;
+    int AHB1RSTR;
+    int AHB2RSTR;
+    int AHB3RSTR;
+    int reserved0;
+    int APB1RSTR;
+    int APB2RSTR;
+    int reserved1a, reserved1b;
+    int AHB1ENR;
+    int AHB2ENR;
+    int AHB3ENR;
+    int reserved2;
+    int APB1ENR, APB2ENR;
+}* RCC_Type;
+
--- a/python/testasm.py	Sun Jul 28 19:07:51 2013 +0200
+++ b/python/testasm.py	Mon Jul 29 20:23:13 2013 +0200
@@ -243,6 +243,14 @@
         self.feed('b henkie')
         self.check('05e004e0 03e002e0 01e000e0 ffe7fee7 fde7fce7 fbe7')
 
+    def testBl(self):
+        self.feed('bl henkie')
+        self.feed('bl henkie')
+        self.feed('henkie:')
+        self.feed('bl henkie')
+        self.feed('bl henkie')
+        self.check('00f0 02f8 00f0 00f8 fff7 feff fff7 fcff')
+
     def testCmpRegReg(self):
         self.feed('cmp r0, r1')
         self.check('8842')
--- a/python/testc3.py	Sun Jul 28 19:07:51 2013 +0200
+++ b/python/testc3.py	Mon Jul 29 20:23:13 2013 +0200
@@ -122,6 +122,17 @@
         self.assertSequenceEqual(expected_ins, actual_ins)
         return ircode
 
+    def testPackage(self):
+        p1 = """package p1;
+        type int A;
+        """
+        p2 = """package p2;
+        import p1;
+        var A b;
+        """
+        self.assertTrue(self.builder.build(p1))
+        self.expectOK(p2)
+
     def testFunctArgs(self):
       snippet = """
          package testargs;
--- a/python/testhexfile.py	Sun Jul 28 19:07:51 2013 +0200
+++ b/python/testhexfile.py	Mon Jul 29 20:23:13 2013 +0200
@@ -30,12 +30,12 @@
 
     def testSave4(self):
         hf = HexFile()
-        hf.addRegion(0xF000, bytes.fromhex('ab')*0x20000)
+        hf.addRegion(0xF000, bytes.fromhex('ab')*0x10000)
         self.saveload(hf)
 
     def testSave5(self):
         hf = HexFile()
-        hf.addRegion(0xF003, bytes.fromhex('ab')*0x20000)
+        hf.addRegion(0xF003, bytes.fromhex('ab')*0x10000)
         self.saveload(hf)
 
     def testMerge(self):