From 42438dd97f14add5c53f1f548774ec0ccd2c1549 Mon Sep 17 00:00:00 2001 From: Chris Pressey Date: Fri, 24 Nov 2017 11:30:20 +0000 Subject: [PATCH] Beginning of: buffers and pointers. --- doc/SixtyPical.md | 2 +- src/sixtypical/model.py | 11 +++++++++ src/sixtypical/parser.py | 46 ++++++++++++++++++++++++-------------- src/sixtypical/scanner.py | 2 +- tests/SixtyPical Syntax.md | 24 ++++++++++++++++++++ 5 files changed, 66 insertions(+), 19 deletions(-) diff --git a/doc/SixtyPical.md b/doc/SixtyPical.md index 1199ab9..a6ac3e5 100644 --- a/doc/SixtyPical.md +++ b/doc/SixtyPical.md @@ -26,7 +26,7 @@ There is also one *type constructor*: * X table (256 entries, each holding a value of type X) -This constructor can only be applied to bytes or words. +This constructor can only be applied to one type, `byte`. Memory locations ---------------- diff --git a/src/sixtypical/model.py b/src/sixtypical/model.py index e509e95..b8419b7 100644 --- a/src/sixtypical/model.py +++ b/src/sixtypical/model.py @@ -58,6 +58,17 @@ class VectorType(ExecutableType): super(VectorType, self).__init__('vector', **kwargs) +class BufferType(Type): + def __init__(self, size): + self.size = size + self.name = 'buffer[%s]' % self.size + + +class PointerType(Type): + def __init__(self): + self.name = 'pointer' + + class Ref(object): def is_constant(self): """read-only means that the program cannot change the value diff --git a/src/sixtypical/parser.py b/src/sixtypical/parser.py index c46dbeb..85efc4d 100644 --- a/src/sixtypical/parser.py +++ b/src/sixtypical/parser.py @@ -3,7 +3,7 @@ from sixtypical.ast import Program, Defn, Routine, Block, Instr from sixtypical.model import ( TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_WORD, TYPE_WORD_TABLE, - RoutineType, VectorType, ExecutableType, + RoutineType, VectorType, ExecutableType, BufferType, PointerType, LocationRef, ConstantRef ) from sixtypical.scanner import Scanner @@ -32,7 +32,7 @@ class Parser(object): def program(self): defns = [] routines = [] - while self.scanner.on('byte', 'word', 'vector'): + while self.scanner.on('byte', 'word', 'vector', 'buffer', 'pointer'): defn = self.defn() name = defn.name if name in self.symbols: @@ -50,25 +50,15 @@ class Parser(object): return Program(defns=defns, routines=routines) def defn(self): - type = None - if self.scanner.consume('byte'): - type = TYPE_BYTE - if self.scanner.consume('table'): - type = TYPE_BYTE_TABLE - elif self.scanner.consume('word'): - type = TYPE_WORD - if self.scanner.consume('table'): - type = TYPE_WORD_TABLE - else: - self.scanner.expect('vector') - type = 'vector' # will be resolved to a Type below + type_ = self.defn_type() + self.scanner.check_type('identifier') name = self.scanner.token self.scanner.scan() (inputs, outputs, trashes) = self.constraints() - if type == 'vector': - type = VectorType(inputs=inputs, outputs=outputs, trashes=trashes) + if type_ == 'vector': + type_ = VectorType(inputs=inputs, outputs=outputs, trashes=trashes) elif inputs or outputs or trashes: raise SyntaxError("Cannot apply constraints to non-vector type") @@ -87,10 +77,32 @@ class Parser(object): if initial is not None and addr is not None: raise SyntaxError("Definition cannot have both initial value and explicit address") - location = LocationRef(type, name) + location = LocationRef(type_, name) return Defn(name=name, addr=addr, initial=initial, location=location) + def defn_type(self): + if self.scanner.consume('byte'): + if self.scanner.consume('table'): + return TYPE_BYTE_TABLE + return TYPE_BYTE + elif self.scanner.consume('word'): + if self.scanner.consume('table'): + return TYPE_WORD_TABLE + return TYPE_WORD + elif self.scanner.consume('vector'): + return 'vector' # will be resolved to a Type by caller + elif self.scanner.consume('buffer'): + self.scanner.expect('[') + self.scanner.check_type('integer literal') + size = int(self.scanner.token) + self.scanner.scan() + self.scanner.expect(']') + return BufferType(size) + else: + self.scanner.expect('pointer') + return PointerType() + def constraints(self): inputs = set() outputs = set() diff --git a/src/sixtypical/scanner.py b/src/sixtypical/scanner.py index c538c3e..3663e9c 100644 --- a/src/sixtypical/scanner.py +++ b/src/sixtypical/scanner.py @@ -29,7 +29,7 @@ class Scanner(object): self.token = None self.type = 'EOF' return - if self.scan_pattern(r'\,|\@|\+|\:|\<|\>|\{|\}', 'operator'): + if self.scan_pattern(r'\,|\@|\+|\:|\<|\>|\{|\}|\[|\]', 'operator'): return if self.scan_pattern(r'\d+', 'integer literal'): return diff --git a/tests/SixtyPical Syntax.md b/tests/SixtyPical Syntax.md index c653eb3..8528e5b 100644 --- a/tests/SixtyPical Syntax.md +++ b/tests/SixtyPical Syntax.md @@ -123,6 +123,30 @@ Repeat with not | } = ok +User-defined memory addresses of different types. + + | byte byt + | word wor + | vector vec + | byte table tab + | + | routine main { + | } + = ok + +Buffer and pointer types. + + | byte byt + | word wor + | vector vec + | byte table tab + | buffer[2048] buf + | pointer ptr + | + | routine main { + | } + = ok + Explicit memory address. | byte screen @ 1024