Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Module refactor #1

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Runme",
"type": "python",
"request": "launch",
"cwd": "${workspaceFolder}",
"module": r"zsc",
"console": "integratedTerminal",
"args": [r"C:\\Users\\steve\\Desktop\\dummy.py"]
}
]
}
183 changes: 183 additions & 0 deletions tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import unittest
import zsc.prepass as prepass
import zsc.compiler as compiler
import ast
import inspect


class TestPrepass(unittest.TestCase):

def test_get_call_name_zfunc(self):
p = prepass.Prepass()
example = ast.parse('''zbrush.IClick("a:b:c")''', mode='eval')
assert (p.get_call_name(example.body)) == ('zbrush', 'IClick')

def test_get_call_name_raw(self):
p = prepass.Prepass()
example = ast.parse('''somefunction()''', mode='eval')
assert (p.get_call_name(example.body)) == ('', 'somefunction')

def test_get_is_zfunc_normal(self):
p = prepass.Prepass()
raw = '''import zbrush\nzbrush.IClick()'''
p.visit(ast.parse(raw))
example = ast.parse('''zbrush.IClick("A")''', mode='eval')
assert (p.is_zbrush_function(example.body))

def test_get_is_zfunc_fail_unrecognized(self):
p = prepass.Prepass()
raw = '''import zbrush\nzbrush.IClick()'''
p.visit(ast.parse(raw))
example = ast.parse('''dummy("A")''', mode='eval')
assert (not p.is_zbrush_function(example.body))

def test_get_zfunc_mod_alias(self):
p = prepass.Prepass()
raw = '''import zbrush as zb\nzb.IClick()'''
p.visit(ast.parse(raw))
example = ast.parse('''zb.IClick("A")''', mode='eval')
assert (p.is_zbrush_function(example.body))

def test_get_zfunc_func_alias(self):
p = prepass.Prepass()
raw = '''from zbrush import IClick as blah'''
p.visit(ast.parse(raw))
example = ast.parse('''blah("A")''', mode='eval')
assert (p.is_zbrush_function(example.body))

def test_get_zfunc_signature(self):
p = prepass.Prepass()
raw = '''from zbrush import IClick as blah'''
p.visit(ast.parse(raw))
assert isinstance(p.get_signature('IClick'), inspect.FullArgSpec)

def test_allows_zbrush_import(self):
p = prepass.Prepass()
raw = '''import zbrush'''
p.visit(ast.parse(raw))

def test_allows_math_import(self):
p = prepass.Prepass()
raw = '''import math'''
p.visit(ast.parse(raw))

def test_allows_random_import(self):
p = prepass.Prepass()
raw = '''import random'''
p.visit(ast.parse(raw))

def test_no_other_import_plain(self):
p = prepass.Prepass()
raw = '''import csv'''
def bad(): return p.visit(ast.parse(raw))
self.assertRaises(prepass.ParseError, bad)

def test_no_other_math_import_aliased(self):
p = prepass.Prepass()
raw = '''import csv as xyz'''
def bad(): return p.visit(ast.parse(raw))
self.assertRaises(prepass.ParseError, bad)

def test_user_function(self):
p = prepass.Prepass()
raw = '''def userfunc():\n return 1'''
p.visit(ast.parse(raw))
call = ast.Call(ast.Name("userfunc"))
assert p.is_user_function(call)

def test_user_function_negative(self):
p = prepass.Prepass()
raw = '''def userfunc():\n return 1'''
p.visit(ast.parse(raw))
call = ast.Call(ast.Name("not_userfunc"))
assert not p.is_user_function(call)

def test_has_return_type(self):
p = prepass.Prepass()
raw = '''import zbrush, math, random'''
p.visit(ast.parse(raw))
call = ast.Call(ast.Name("GetActiveToolPath"))
assert p.has_return_type(call)

def test_has_return_type_neg(self):
p = prepass.Prepass()
raw = '''import zbrush, math, random'''
p.visit(ast.parse(raw))
call = ast.Call(ast.Name("MTransformSet"))
assert not p.has_return_type(call)

def test_return_type_math(self):
p = prepass.Prepass()
raw = '''import zbrush, math, random'''
p.visit(ast.parse(raw))
call = ast.Call(ast.Name("sin"))
assert p.has_return_type(call)

def test_return_type_random(self):
p = prepass.Prepass()
raw = '''import zbrush, math, random'''
p.visit(ast.parse(raw))
call = ast.Call(ast.Name("randint"))
assert p.has_return_type(call)

def test_return_type_user(self):
# note that user functions _CANT_ have return types
# in zbrush, so this ignores the python. The compiler
# raises an error for this
p = prepass.Prepass()
raw = '''def userfunc():\n return 1'''
p.visit(ast.parse(raw))
call = ast.Call(ast.Name("usefunc"))
assert not p.has_return_type(call)



class TestAnalyzer(unittest.TestCase):

def parse (self, stringval):
tree = ast.parse(stringval)
p = prepass.Prepass()
p.visit(tree)
analyzer = compiler.Analyzer(0, input_file="dummy", prepass=p)
return analyzer, tree



def test_assign_int(self):
analyzer, tree = self.parse('''a = 1''')
analyzer.visit(tree)
assert analyzer.format() == '[VarDef, a, 1]'

def test_assign_float(self):
analyzer, tree = self.parse('''a = -1.0''')
analyzer.visit(tree)
assert analyzer.format() == '[VarDef, a, -1.0]'

def test_assign_str(self):
analyzer, tree = self.parse('''a = "fred"''')
analyzer.visit(tree)
assert analyzer.format() == '[VarDef, a, "fred"]'

def test_assign_var(self):
analyzer, tree = self.parse('''a = 1\nb = a''')
analyzer.visit(tree)
assert analyzer.format() == '[VarDef, a, 1]\n[VarDef, b, #a]'

def test_assign_var_neg(self):
analyzer, tree = self.parse('''a = 1\nb = -a''')
analyzer.visit(tree)
assert analyzer.format() == '[VarDef, a, 1]\n[VarDef, b, [NEG, #a]]'

def test_assign_def_vs_set(self):
# use VarDef at the top level but VarSet inside of functions
analyzer, tree = self.parse('''a = 1\ndef func(input, output):\n temp = input + 1\n output = temp''')
analyzer.visit(tree)
result = analyzer.format()
assert '[VarDef, a, 1]' in result
assert '[VarSet, temp, ' in result
assert '[VarSet, output' in result



if __name__ == '__main__':
unittest.main()
Empty file added zsc/__init__.py
Empty file.
21 changes: 21 additions & 0 deletions zsc/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import zsc.compiler as compiler
import argparse

if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog="zsc",
description=f'Python to ZScript transpiler ({compiler.VERSION})'
)
parser.add_argument("input", help="path to python source file")
parser.add_argument(
"--output", help="optional output file (otherwise, uses the same name as the input file with .txt extension)")
parser.add_argument(
"--show", help="if true, print the transpiled file to stdout", action='store_true')

args = parser.parse_args()
output, result = compiler.compile(args.input, out_filename=args.output or '')

if args.show:
print(result)
else:
print(output)
Loading