diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000..b10d6f4 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,12 @@ +# This configuration file was automatically generated by Gitpod. +# Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file) +# and commit this file to your remote git repository to share the goodness with others. + +tasks: + - init: pip install . +vscode: + extensions: + - ms-python.python + + + - ms-toolsai.jupyter diff --git a/setup.py b/setup.py index 836b107..c8c0878 100644 --- a/setup.py +++ b/setup.py @@ -2,12 +2,12 @@ from setuptools import setup setup ( - name = 'snakevm', - version = '1.0.1', + name = 'The Snake Programming Language\'s Simple Virtual Program Assembler', + version = '1.0.2', description = 'A simple virtual machine and program assembler', author = 'Travis Cunningham', author_email = 'travcunn@umail.iu.edu', - url = 'https://github.com/travcunn/simple_cpu', + url = 'https://github.com/travcunn/snake-lang', license = 'MIT', packages = ['snake'], package_dir = {'snake': 'snake'}, diff --git a/snake/__init__.py b/snake/__init__.py index e69de29..fa9ad2c 100644 --- a/snake/__init__.py +++ b/snake/__init__.py @@ -0,0 +1,86 @@ +# Assembler recreation of the Snake language-EXCEPT it's the lite version of the assembler and uses less data. +OP_CODES = { + "input": 0, + "cla.": 1, + "add.": 2, + "tac.": 3, + "software": 4, + "output": 5, + "stop": 6, + "subtraction": 7, + "jumping": 8, + "halt": 9, + "mul.": 10, + "div": 11, + "snoop": 12 +} +class InstructionError(Exception): + pass +class Assembler(object): + def __init__(self, inputfile): + self.contents = [line.rstrip('\n') for line in inputfile.readlines()] + self.generated_records = ["002", "800"] + self.data_p = 4 + self.code_p = 10 + # key:value => label:addr + self.symbol_table = {} + def first_pass(self): + # Collect all symbols in the first pass. + code_p = self.code_p + data_p = self.code_p + for line in self.contents: + tks = [tk.lower() for tk in line.split()] + #: pass space or tab + if not tks: + continue + #: label + if tks[0] not in OP_CODES and len(tks) >= 3: + label_name = tks[0] + if tks[1] == 'data': + self.symbol_table[label_name] = data_p + else: + self.symbol_table[label_name] = code_p + tks.remove(tks[0]) + if len(tks) >= 2 and tks[0] in OP_CODES: + code_p += 1 + if len(tks) >= 2 and tks[0] == 'data': + data_p += 1 + def second_pass(self): + for line in self.contents: + tks = [tk.lower for tk in line.split] + #: pass space and tab + if not tks: + continue + #: label + if tks[0] not in OP_CODES and len(tks) >= 3: + tks.remove(tks[0]) + #: data + if len(tks) >= 2 and tks[0] == 'data': + self.generated_records.append(self.pad(self.data_p)) + self.generated_records.append(tks[1]) + self.data_p += 1 + continue + #: instruction + if len(tks) >= 2 and tks[0] in OP_CODES: + operation = tks[0] + address = tks[1] + op = str(OP_CODES[operation]) + if address in self.symbol_table: + address = self.pad(self.symbol_table[address], length=2) + code = op + address + self.generated_records.append(self.pad(self.code_p)) + self.generated_records.append(code) + self.code_p += 1 + continue + raise InstructionError("Instruction error ocurred: %s" % (tks,)) + self.generated_records.append("002") + self.generated_records.append("810") + def assemble(self): + self.first_pass() + self.second_pass() + @staticmethod + def pad(data, length=3): + # Pads make either an integer or number in string format with 0's. + padding = '0' * length + data = '%s%s' % (padding) + return data[-length:]