Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/pynxc/pynxc.pyw
diff options
context:
space:
mode:
Diffstat (limited to 'pynxc/pynxc.pyw')
-rwxr-xr-xpynxc/pynxc.pyw1392
1 files changed, 1392 insertions, 0 deletions
diff --git a/pynxc/pynxc.pyw b/pynxc/pynxc.pyw
new file mode 100755
index 0000000..820fb2a
--- /dev/null
+++ b/pynxc/pynxc.pyw
@@ -0,0 +1,1392 @@
+#!/usr/bin/env python
+from __future__ import with_statement
+
+__author__ = 'Brian Blais <bblais@bryant.edu>'
+__version__ = (0,1,6)
+
+
+import ast_template
+import sys
+from compiler import parse, walk
+from compiler.consts import *
+from waxy import *
+import os
+import subprocess
+from optparse import OptionParser
+import re
+import yaml
+
+
+pynxc_root,junk=os.path.split(sys.argv[0])
+#pynxc_root=os.getcwd()
+
+
+class MyObject(object):
+
+ def __init__(self,name,type='default'):
+
+ self.name=name
+ self.type=type
+ self.datatype=None
+ self.value=None
+
+
+ self.variables=[]
+
+ def __repr__(self):
+ return self.type+" "+self.name+" of datatype "+self.datatype.__repr__()+" with value "+self.value.__repr__()
+
+
+class Variable(MyObject):
+
+ def __init__(self,name,datatype='default'):
+
+
+ super(Variable,self).__init__(name,'variable')
+ self.datatype=datatype
+
+
+class Function(MyObject):
+
+ def __init__(self,name,variables=[]):
+
+
+ super(Function,self).__init__(name,'function')
+ self.variables=variables
+
+
+
+
+file_lines=[]
+
+class SecondPassVisitor(ast_template.Visitor):
+ """This object goes through and output the code"""
+
+ def __init__(self,fv,stream=sys.stdout,debug=False):
+
+ ast_template.Visitor.__init__(self,stream,debug)
+
+
+ self.fv=fv # first-pass visitor
+ self.stream=stream
+ self.erase_assign=False
+ self.buffer=[]
+ self.semicolon=True
+
+ self.writef('#include "NXCDefs.h"\n')
+ self.writef(open(os.path.join(pynxc_root,"MyDefs.h"),'rt').read())
+
+
+ for d in fv.defines:
+ self.writef('#define %s %s\n' % (d[0],d[1]))
+
+ self.print_structure_definitions(fv.struct_types)
+
+ self.print_typedefs(fv.typedefs)
+
+ if self.debug:
+ print "Module Variables Printing "
+
+ self.print_variable_definitions(fv.functions['module'].variables)
+ self.scope=['module']
+
+
+ def type2str(self,datatype):
+ if datatype=='Integer':
+ return 'int'
+ elif datatype=='IntegerPtr':
+ return 'int&'
+ elif datatype=='Word':
+ return 'word'
+ elif datatype=='Long':
+ return 'long'
+ elif datatype=='Byte':
+ return 'byte'
+ elif datatype=='Short':
+ return 'short'
+ elif datatype=='String':
+ return 'string'
+ elif datatype=='Mutex':
+ return 'mutex'
+ elif datatype in self.fv.struct_types:
+ return datatype
+ else:
+ return 'int'
+
+ def print_typedefs(self,typedefs):
+
+ for types in typedefs:
+ self.write('typedef %s %s;' % (typedefs[types],types))
+ self.NEWLINE()
+ self.flush()
+
+ def print_structure_definitions(self,struct_types):
+
+ for key in struct_types:
+ self.write('struct %s ' % key)
+ self.INDENT()
+ variables=struct_types[key]
+ for var in variables:
+ self.write(self.type2str(variables[var].datatype))
+ self.write(' %s' % variables[var].name)
+ self.write(';')
+ self.NEWLINE()
+ self.DEDENT()
+ self.write(';')
+ self.NEWLINE()
+
+
+ def print_variable_definitions(self,variables):
+ for var in variables:
+
+
+ if self.debug:
+ print " Variable ",variables[var]
+
+ self.write(self.type2str(variables[var].datatype))
+
+ self.write(' %s' % variables[var].name)
+
+ if not variables[var].value is None:
+ if isinstance(variables[var].value,list):
+ self.write('[]')
+ if not variables[var].value==[]:
+ self.write('={')
+ for v in variables[var].value:
+ self.write(v.__repr__())
+ if not v == variables[var].value[-1]:
+ self.write(',')
+ self.write('}')
+
+
+
+ else:
+ val=variables[var].value.__repr__()
+ self.write('= %s' % val.replace("'",'"'))
+ self.write(';')
+ self.NEWLINE()
+
+ if variables[var].datatype in self.fv.struct_types:
+ variables2=self.fv.struct_types[variables[var].datatype]
+ for var2 in variables2:
+ if variables2[var2].value:
+ val2=variables2[var2].value.__repr__()
+
+ self.write('%s.%s' % (var,variables2[var2].name))
+ self.write('= %s' % val2.replace("'",'"'))
+ self.write(';')
+ self.NEWLINE()
+
+
+
+ self.flush()
+
+
+ def flush(self):
+
+ if self.buffer:
+ for s in self.buffer:
+ s=s.replace("'",'"')
+ self.stream.write(s)
+
+ self.buffer=[]
+
+ def DEDENT(self,with_semicolon=False):
+ self.indents -=1
+ self.NEWLINE()
+ self.write('}')
+ if with_semicolon:
+ self.write(';')
+ self.NEWLINE()
+
+ def INDENT(self):
+ self.indents += 1
+ self.write(' {')
+ self.NEWLINE()
+
+ def NEWLINE(self):
+ self.write('\n')
+ self.write(' ' * 4 * self.indents )
+
+ def write(self, data):
+ self.buffer.append(data)
+
+
+ def writef(self, data):
+ self.write(data)
+ self.flush()
+
+
+ def visitBlock(self, block):
+ self.INDENT()
+ self.v(block)
+ self.DEDENT()
+
+ def visitAdd(self, node):
+ self.write("(")
+ self.v(node.left)
+ self.write(" + ")
+ self.v(node.right)
+ self.write(")")
+
+ def visitAnd(self, node):
+ self.write("(")
+ for i in range(len(node.nodes)):
+ self.write("(")
+ self.v(node.nodes[i])
+ self.write(")")
+ if i < (len(node.nodes) - 1):
+ self.write(" && ")
+ self.write(")")
+
+ def visitAssAttr(self, node):
+ if self.debug:
+ print 'visitSecondVisitorAssAttr'
+ self.v(node.expr, self)
+ self.write(".%s" % node.attrname)
+
+ def visitAssName(self, node):
+ self.write(node.name)
+
+ def visitAssign(self, node):
+ self.flush()
+ self.erase_assign=False
+ n=node.nodes[0]
+
+
+ if self.scope[-1]=='module':
+ return
+
+# try:
+# if (n.name == n.name.upper()) and (len(n.name)>2): # a definition
+# return
+# except AttributeError:
+# pass # probably a subscript?
+
+ for i in range(len(node.nodes)):
+ n = node.nodes[i]
+ self.v(n)
+ if i < len(node.nodes):
+ self.write(" = ")
+ self.v(node.expr)
+
+ self.write("; ")
+ self.NEWLINE()
+
+
+ if self.erase_assign:
+ self.buffer=[]
+
+ self.flush()
+
+
+ def visitAugAssign(self, node):
+ self.v(node.node)
+ self.write(" %s " % node.op)
+ self.v(node.expr)
+ self.write("; ")
+ self.NEWLINE()
+
+
+ def visitBitand(self, node):
+ for i in range(len(node.nodes)):
+ self.v(node.nodes[i])
+ if i < (len(node.nodes) - 1):
+ self.write(" & ")
+
+ def visitBitor(self, node):
+ for i in range(len(node.nodes)):
+ self.v(node.nodes[i])
+ if i < (len(node.nodes) - 1):
+ self.write(" | ")
+
+ def visitBitxor(self, node):
+ for i in range(len(node.nodes)):
+ self.v(node.nodes[i])
+ if i < (len(node.nodes) - 1):
+ self.write(" ^ ")
+
+ def visitBreak(self, node):
+ self.write("break; ")
+ self.NEWLINE()
+
+ def visitFunction(self, node):
+ self.scope.append('function')
+
+ hasvar = haskw = hasone = hasboth = False
+
+ ndefaults = len(node.defaults)
+
+ if node.flags & CO_VARARGS:
+ hasone = hasvar = True
+ if node.flags & CO_VARKEYWORDS:
+ hasone = haskw = True
+ hasboth = hasvar and haskw
+
+ kwarg = None
+ vararg = None
+ defargs = []
+ newargs = node.argnames[:]
+
+ if ndefaults:
+ for i in range(ndefaults):
+ defargs.append((newargs.pop(), node.defaults.pop()))
+ defargs.reverse()
+
+ func_type=self.fv.functions[node.name].datatype
+ if not func_type:
+ func_type='void'
+
+ if func_type=='default':
+ func_type='int'
+
+ if node.name=='main':
+ self.write("task %s(" % node.name)
+ elif node.name.find('task_')==0:
+ self.write("task %s(" % node.name)
+ elif node.name.find('sub_')==0:
+ self.write("sub %s(" % node.name)
+ elif node.name.find('inline_')==0:
+ self.write("inline %s %s(" % (func_type,node.name.replace('inline_','')))
+ else:
+ self.write("%s %s(" % (func_type,node.name))
+
+
+ for i in range(len(newargs)):
+ if isinstance(newargs[i], tuple):
+ self.write("(%s, %s)" % newargs[i])
+ else:
+ self.write("int "+newargs[i])
+ if i < len(newargs) - 1:
+ self.write(", ")
+ if defargs and len(newargs):
+ self.write(", ")
+
+ for i in range(len(defargs)):
+ name, default = defargs[i]
+ typename=default.node.name
+
+
+
+ self.write("%s %s" % (self.type2str(typename),name))
+ #self.v(default)
+ if i < len(defargs) - 1:
+ self.write(", ")
+
+ if vararg:
+ if (newargs or defargs):
+ self.write(", ")
+ self.write(vararg)
+ if kwarg:
+ if (newargs or defargs or vararg):
+ self.write(", ")
+ self.write(kwarg)
+
+ self.write(") ")
+ self.INDENT()
+
+ self.print_variable_definitions(self.fv.functions[node.name].variables)
+
+ self.v(node.code)
+ self.DEDENT()
+
+ self.flush()
+ self.scope.pop()
+
+
+ def visitCallFunc(self, node):
+
+ name=node.node.name
+
+ if name=="ASM": # raw ASM
+ s=node.args[0].value
+
+ self.write("asm{%s}" % s)
+
+ return
+
+ if name=="NXC":
+ s=node.args[0].value
+
+ self.write("%s" % s)
+
+ return
+
+ if name=="DEFINE":
+ s=node.args[1].value
+ d=node.args[0].value
+
+ self.write("#define %s %s" %(d,s))
+ self.NEWLINE()
+ self.semicolon=False
+ return
+
+ self.v(node.node)
+ self.write("(")
+ for i in range(len(node.args)):
+ self.v(node.args[i])
+ if i < (len(node.args) - 1):
+ self.write(", ")
+ if node.star_args:
+ if len(node.args):
+ self.write(", ")
+ self.write("*")
+ self.v(node.star_args)
+ if node.dstar_args:
+ if node.args or node.star_args:
+ self.write(", ")
+ self.write("**")
+ self.v(node.dstar_args)
+ self.write(")")
+
+ if name in self.fv.types:
+ self.erase_assign=True
+
+
+ def visitClass(self, node):
+ self.scope.append('class')
+
+ self.flush()
+ for i in range(len(node.bases)):
+ self.v(node.bases[i])
+ self.INDENT()
+ self.v(node.code)
+ self.DEDENT()
+
+ self.buffer=[] # get rid of all of the stuff in a class def
+ self.scope.pop()
+
+
+ def visitCompare(self, node):
+ self.write("(")
+ self.v(node.expr)
+
+ for operator, operand in node.ops:
+ self.write(" %s " % operator)
+ self.v(operand)
+ self.write(")")
+
+ def visitConst(self, node):
+ self.write(repr(node.value))
+
+ def visitContinue(self, node):
+ self.write("continue; ")
+
+ def visitDiscard(self, node):
+ self.semicolon=True
+
+ # deal with empty statements, so it doesn't print None
+ try:
+ if node.expr.value is None:
+ pass
+ else:
+ self.v(node.expr)
+ if self.semicolon:
+ self.write(";")
+ self.NEWLINE()
+ except AttributeError:
+ self.v(node.expr)
+ if self.semicolon:
+ self.write(";")
+ self.NEWLINE()
+
+ def visitDiv(self, node):
+ self.v(node.left)
+ self.write(" / ")
+ self.v(node.right)
+
+
+ def visitFor(self, node):
+
+
+ children=node.list.getChildNodes()
+ start='0'
+ end='1'
+ step='1'
+
+ if self.debug:
+ print node.assign.name
+ print dir(node.assign)
+
+ print node.list
+ print dir(node.list)
+
+ print node.list.getChildren()
+
+ print children
+
+ if children[0].name=='range':
+ vals=[v.asList()[0] for v in children[1:]]
+ if node.assign.name=='repeat': # keyword repeat
+ if len(vals)==1:
+ end=vals[0]
+ else:
+ raise ValueError,"Bad for-loop construction"
+
+ self.write("repeat(%s) " % (end))
+
+ else:
+ if len(vals)==1:
+ end=vals[0]
+ elif len(vals)==2:
+ start=vals[0]
+ end=vals[1]
+ elif len(vals)==3:
+ start=vals[0]
+ end=vals[1]
+ step=vals[2]
+ else:
+ raise ValueError,"Bad for-loop construction"
+
+ varname=node.assign.name
+ self.write("for (%s=%s; %s<%s; %s+=%s) " % (varname,start,
+ varname,end,
+ varname,step))
+
+ self.INDENT()
+ self.v(node.body)
+ self.DEDENT()
+ else:
+ raise ValueError,"For-loop construction not implemented"
+
+
+
+
+ def visitGenExpr(self, node):
+ self.write("(")
+ self.v(node.code)
+ self.write(")")
+
+ def visitGetattr(self, node):
+ self.v(node.expr)
+ self.write(".%s" % node.attrname)
+
+ def visitIf(self, node):
+ flag=False
+ for c, b in node.tests:
+ if not flag:
+ self.write("if (")
+ else:
+ self.write("else if (")
+ self.v(c)
+ self.write(') ')
+ self.INDENT()
+ self.v(b)
+ self.DEDENT()
+ flag=True
+ if node.else_:
+ self.write("else ")
+ self.INDENT()
+ self.v(node.else_)
+ self.DEDENT()
+
+ def visitKeyword(self, node):
+ self.write(node.name)
+ self.write("=")
+ self.v(node.expr)
+
+
+ def visitInvert(self, node):
+ self.write("~")
+ self.v(node.expr)
+
+ def visitLeftShift(self, node):
+ self.v(node.left)
+ self.write(" << ")
+ self.v(node.right)
+
+ def visitMod(self, node):
+ self.v(node.left)
+ self.write(" % ")
+ self.v(node.right)
+
+ def visitMul(self, node):
+ self.v(node.left)
+ self.write(" * ")
+ self.v(node.right)
+
+ def visitName(self, node):
+
+ if node.name=='False':
+ self.write("false")
+ elif node.name=='True':
+ self.write("true")
+ else:
+ self.write(node.name.replace('inline_',''))
+
+ def visitNot(self, node):
+ self.write(" !(")
+ self.v(node.expr)
+ self.write(")")
+
+ def visitOr(self, node):
+ self.write("(")
+ for i in range(len(node.nodes)):
+ self.write("(")
+ self.v(node.nodes[i])
+ self.write(")")
+ if i < len(node.nodes) - 1:
+ self.write(" || ")
+ self.write(")")
+
+
+ def visitPass(self, node):
+ self.write("// pass ")
+
+ def visitReturn(self, node):
+ try:
+ if node.value.value is None:
+ self.write('return;')
+ else:
+ self.write('return(%s);' % node.value.value.__repr__())
+
+ except TypeError:
+ pass
+ except AttributeError:
+
+ self.write("return(")
+ self.v(node.value)
+ self.write(");")
+
+ def visitRightShift(self, node):
+ self.v(node.left)
+ self.write(" >> ")
+ self.v(node.right)
+
+ def visitSubscript(self, node):
+ isdel = False
+ if node.flags == OP_DELETE: isdel = True
+ isdel and self.write("del ")
+ self.v(node.expr)
+ self.write("[")
+ for i in range(len(node.subs)):
+ self.v(node.subs[i])
+ if i == len(node.subs) - 1:
+ self.write("]")
+ node.flags == OP_DELETE and self.NEWLINE()
+
+ def visitSub(self, node):
+ self.write("(")
+ self.v(node.left)
+ self.write(" - ")
+ self.v(node.right)
+ self.write(")")
+
+ def visitUnaryAdd(self, node):
+ self.write("+")
+ self.v(node.expr)
+
+ def visitUnarySub(self, node):
+ self.write("-")
+ self.v(node.expr)
+
+ def visitWhile(self, node):
+ self.write("while (")
+ self.v(node.test)
+ self.write(") ")
+ self.INDENT()
+ self.v(node.body)
+ if node.else_:
+ self.DEDENT()
+ self.write("else:")
+ self.INDENT()
+ self.v(node.else_)
+ self.DEDENT()
+
+
+
+
+
+
+class FirstPassVisitor(ast_template.Visitor):
+ """This object goes through and gets all of the variables.
+ The second pass will output the code"""
+
+ def __init__(self,stream=sys.stdout,debug=False):
+
+ ast_template.Visitor.__init__(self,stream,debug)
+ self.variables={}
+
+ self.return_datatype=None
+ self.types=['Byte','Short','Word','String','Mutex','Integer','Long','Struct']
+ self.struct_types={}
+ self.functions={}
+ self.functions['module']=Function('module',self.variables)
+
+ self.variables_assign=[]
+ self.kwassign=[]
+ self.use_kwassign=False
+
+ self.typedefs={}
+
+ self.scope=['module']
+
+ self.use_typedef=False
+
+ def visitClass(self, node):
+ self.scope.append('class')
+
+ variables={}
+ old_self_variables=self.variables
+ self.variables=variables
+
+ if self.debug:
+ print "myvisitClass"
+ print node.name
+
+ basename=node.bases[0].name
+ for i in range(len(node.bases)):
+ self.v(node.bases[i])
+
+
+ self.use_typedef=False
+ self.v(node.code)
+
+ if self.use_typedef:
+ self.typedefs[node.name]=basename
+ self.types.append(node.name)
+ else:
+ self.struct_types[node.name]=variables
+ self.types.append(node.name)
+ self.variables=old_self_variables
+ self.scope.pop()
+
+
+
+ def visitPass(self, node):
+ if self.scope[-1]=='class':
+ self.use_typedef=True
+
+ def visitBlock(self, block):
+ if self.debug:
+ print "myvisitBlock"
+ self.v(block)
+
+ def visitAssName(self, node):
+ if self.debug:
+ print 'visitAssName'
+ if node.flags == OP_DELETE:
+ print "del ",
+ print node.name
+
+ n=node
+
+ self.variables_assign.append(n.name)
+
+ if n.name not in self.variables:
+ self.variables[n.name]=Variable(n.name)
+ if self.debug:
+ print "MyAddVar",n.name
+
+ def visitReturn(self, node):
+ #self.write("return ")
+ #self.v(node.value)
+ try:
+ if node.value.value is None:
+ self.return_datatype='void'
+ else:
+ if isinstance(node.value.value,int):
+ self.return_datatype='int'
+ else:
+ raise TypeError,"Unknown type for "+str(node.value.value)
+
+ except TypeError:
+ pass
+ except AttributeError: # a name?
+ name=node.value.name
+ if name in self.variables:
+ self.return_datatype=self.variables[name].datatype
+ else:
+ raise NameError, "Name"+name+"not found"
+
+ def visitFor(self, node):
+ if self.debug:
+ print 'myvisitFor'
+
+ if node.assign.name!='repeat': # keyword repeat
+ self.v(node.assign)
+
+ self.v(node.body)
+
+
+
+ def visitAssign(self, node):
+ if self.debug:
+ print 'MyvisitAssign'
+
+ self.variables_assign=[]
+ for i in range(len(node.nodes)):
+ n = node.nodes[i]
+ if self.debug:
+ print " Node ",n
+ self.v(n)
+
+ if self.debug:
+ print "varassign ",self.variables_assign
+ a=node.expr.asList()[0]
+ print "varassign expr",node.expr,node.expr.asList()[0],type(a)
+
+ if self.scope[-1]=='module':
+ if self.debug:
+ print "Module Variables"
+ for name in self.variables_assign:
+ val=node.expr.asList()[0]
+ self.variables[name].value=val
+ if isinstance(val,str):
+ self.variables[name].datatype='String'
+ if self.debug:
+ print " ",self.variables[name]
+
+
+ self.v(node.expr)
+
+
+ def visitKeyword(self, node):
+ if self.debug:
+ print 'myvisitKeyword'
+
+ if not self.use_kwassign:
+ self.v(node.expr)
+ return
+
+
+
+ def visitCallFunc(self, node):
+ if self.debug:
+ print 'myvisitCallFunc'
+ print 'funcname: ',node.node.name
+
+ name=node.node.name
+
+
+ if not name in self.types:
+ self.v(node.node)
+ for i in range(len(node.args)):
+ self.v(node.args[i])
+
+ return
+
+ for v in self.variables_assign:
+ if (name=='Byte' or name=='Word' or name=='Short' or
+ name=='String' or name=='Integer' or name=='Long' or
+ name=='Mutex'):
+
+ self.variables[v].datatype=name
+ try:
+ self.variables[v].value=node.args[0].value
+ except IndexError:
+ self.variables[v].value=None # to fix the mutex problem
+ # was: pass # use the default value
+ except AttributeError: # list? or mutex
+ nodelist=node.args[0].asList()
+ vallist=[]
+ for l in nodelist:
+ vallist.append(l.value)
+
+ self.variables[v].value=vallist
+ elif name=='Struct':
+
+
+ self.use_kwassign=True
+
+
+ struct_name=node.args[0].value
+
+ if not struct_name in self.struct_types:
+ self.struct_types.append(struct_name)
+
+ for i in range(1,len(node.args)):
+ if self.debug:
+ print node.args[i]
+ print dir(node.args[i])
+ fun=node.args[i].name
+ #self.v(node.args[i])
+ if self.debug:
+ print " fun",fun
+ elif name in self.types:
+ self.variables[v].datatype=name
+ try:
+ self.variables[v].value=node.args[0].value
+ except IndexError:
+ pass # use the default value
+ except AttributeError: # list?
+ self.variables[v].value=[]
+
+
+ def visitFunction(self, node):
+ self.scope.append('function')
+ self.return_datatype=None
+
+ variables={}
+ old_self_variables=self.variables
+ self.variables=variables
+
+ if self.debug:
+ print "myvisitFunction"
+ print node.name
+ hasvar = haskw = hasone = hasboth = False
+
+ ndefaults = len(node.defaults)
+
+ if node.flags & CO_VARARGS:
+ hasone = hasvar = True
+ if node.flags & CO_VARKEYWORDS:
+ hasone = haskw = True
+ hasboth = hasvar and haskw
+
+ kwarg = None
+ vararg = None
+ defargs = []
+ newargs = node.argnames[:]
+
+
+ self.v(node.code)
+
+ self.functions[node.name]=Function(node.name,variables)
+ self.functions[node.name].datatype=self.return_datatype
+ self.variables=old_self_variables
+ self.scope.pop()
+
+
+ # remove those variables that are global
+ remove_var=[]
+ for var in self.functions[node.name].variables:
+ if (var in self.variables and
+ self.functions[node.name].variables[var].datatype=='default'):
+
+ remove_var.append(var)
+
+ for r in remove_var:
+ self.functions[node.name].variables.pop(r)
+
+
+def python_to_nxc(pyfile,nxcfile=None,debug=False):
+ global file_lines
+
+ filename = pyfile
+
+ f = open(filename, 'U')
+ codestring = f.read()
+ f.close()
+ if codestring and codestring[-1] != '\n':
+ codestring = codestring + '\n'
+
+ file_lines=open(filename).readlines()
+ filestr=codestring
+
+
+ defines=re.findall('\s*DEFINE (.*?)=(.*)',filestr)
+ filestr=re.sub('\s*DEFINE (.*?)=(.*)',"",filestr)
+
+
+ if debug:
+ print "Filestr"
+ print filestr
+
+ ast = parse(filestr)
+ v = FirstPassVisitor(debug=debug)
+ v.v(ast)
+
+ v.defines=defines
+
+ if nxcfile:
+ fid=open(nxcfile,'wt')
+ else:
+ fid=sys.stdout
+
+ v2 = SecondPassVisitor(v,debug=debug,stream=fid)
+ v2.v(ast)
+ v2.flush()
+
+ if not fid==sys.stdout:
+ fid.close()
+
+def readconfig(fname):
+ config={'firmware':'105'}
+
+ if os.path.exists(fname):
+ data=yaml.load(open(fname))
+ config.update(data)
+
+ return config
+
+def main():
+
+ config=readconfig('pynxc.yaml')
+ nxc=os.path.join("nxc",sys.platform,'nbc')
+ if not os.path.exists(nxc):
+ nxc = 'nbc' # expect 'nbc' in the binary PATH
+
+ usage="usage: %prog [options] [filename]"
+ parser = OptionParser(usage=usage)
+
+ parser.add_option('-c', '--compile', dest="compile",
+ help='compile to nxc code only',default=False,
+ action="store_true")
+ parser.add_option('--debug', dest="debug",
+ help='show debug messages',default=False,
+ action="store_true")
+ parser.add_option('--show_nxc', dest="show_nxc",
+ help='show the nxc code',default=False,
+ action="store_true")
+ parser.add_option('-d', '--download', dest="download",
+ help='download program',default=False,
+ action="store_true")
+ parser.add_option('-B', '--bluetooth', dest="bluetooth",
+ help='enable bluetooth',default=False,
+ action="store_true")
+ parser.add_option('--firmware', dest="firmware",
+ help='firmware version (105, 107, or 128)',default=config['firmware'])
+ parser.add_option('--command', dest="nxc",
+ help='what is the nxc/nqc command',default=nxc,
+ metavar="<command>")
+
+
+ options, args = parser.parse_args()
+ if len(args) < 1:
+ parser.print_help()
+ raise SystemExit
+
+ options.firmware=config['firmware']
+
+ # sanity check on the options
+
+ if (options.download) and (options.compile):
+ print "conflicting options"
+ parser.print_help()
+ raise SystemExit
+
+
+ nxc_root,nxc=os.path.split(options.nxc)
+ s=nxc.lower()
+
+ filename = args[0]
+
+ for filename in args:
+
+ root,ext=os.path.splitext(filename)
+
+ nxc_filename=root+".nxc"
+ rxe_filename=root+".rxe"
+
+ python_to_nxc(filename,nxc_filename,debug=options.debug)
+ print "Wrote %s." % (nxc_filename)
+
+ if options.show_nxc:
+ fid=open(nxc_filename)
+ print fid.read()
+ fid.close()
+
+ if not options.compile:
+
+ cmd=options.nxc+" "
+ if options.bluetooth:
+ cmd+=' -BT '
+
+ cmd=cmd+ "'%s'" % nxc_filename+ " -I='%s' -I=%s/ -v=%s -O='%s'" % (nxc_root,
+ pynxc_root,
+ options.firmware,
+ rxe_filename)
+ print cmd
+ a=os.system(cmd)
+
+ if options.download:
+ print "Downloading...",
+ cmd=options.nxc+" "
+ cmd=cmd+ nxc_filename+ " -I='%s/' -I='%s/' v=%s -d" % (nxc_root,
+ pynxc_root,
+ options.firmware)
+ a=os.system(cmd)
+ nxtcom=os.path.join(nxc_root,'nxtcom')
+ print nxtcom
+ if os.path.exists(nxtcom):
+ cmd='%s %s' % (nxtcom,rxe_filename)
+ a=os.system(cmd)
+
+ print "done."
+
+
+ return
+
+
+class MainFrame(Frame):
+
+ def Body(self):
+ self.ReadConfig()
+
+ self.nxc=os.path.join("nxc",sys.platform,'nbc')
+ if not os.path.exists(self.nxc):
+ nxc = 'nbc' # expect 'nbc' in the binary PATH
+
+ self.prog=None
+
+ self.CreateMenu()
+
+ self.textbox = TextBox(self, multiline=1, readonly=1,
+ Font=Font("Courier New", 10), Size=(650,500),
+ Value='PyNXC Version '+str(__version__)+"\n" +
+ "Firmware Version "+self.firmware_version+"\n")
+ self.AddComponent(self.textbox, expand='both')
+
+ self.Pack()
+ self.CenterOnScreen()
+
+ cmdlist=[self.nxc]
+ self.DoCmd(cmdlist)
+
+ self.ResetTitle()
+
+ def ReadConfig(self):
+
+ config=readconfig('pynxc.yaml')
+ self.firmware_version=str(config['firmware'])
+
+ def UpdateConfig(self):
+
+ config={'firmware':self.firmware_version}
+ with open("pynxc.yaml",'w') as fid:
+ yaml.dump(config,fid,default_flow_style=False)
+
+ def CreateMenu(self):
+
+
+ menubar = MenuBar()
+
+ menu1 = Menu(self)
+ menu1.Append("L&oad Program File", self.Load, "Load a .py file",hotkey="Ctrl+O")
+ menu1.Append("&Quit", self.Quit, "Quit",hotkey="Ctrl+Q")
+ menubar.Append(menu1, "&File")
+
+ menu1 = Menu(self)
+ menu1.Append("Con&vert", self.OnlyConvert)
+ menu1.Append("&Compile", self.Compile,hotkey="Ctrl+C")
+ menu1.Append("Compile and &Download", self.Download,hotkey="Ctrl+D")
+ menubar.Append(menu1, "&Program")
+ self.menubar=menubar
+
+ self.nxt_menu = Menu(self)
+ self.nxt_menu.Append("&Info", self.NXT_Info)
+ self.bluetooth_menu=self.nxt_menu.Append("Enable &Bluetooth", type='check')
+
+ submenu=Menu(self)
+ self.firmware_menus=[
+ submenu.Append("Version 105",type='radio',event=self.FirmwareVersion),
+ submenu.Append("Version 107",type='radio',event=self.FirmwareVersion),
+ submenu.Append("Version 128",type='radio',event=self.FirmwareVersion),
+ ]
+ if self.firmware_version=='107':
+ self.firmware_menus[1].Check(True)
+ elif self.firmware_version=='128':
+ self.firmware_menus[2].Check(True)
+ else:
+ self.firmware_menus[0].Check(True)
+ self.firmware_version='105'
+ self.UpdateConfig()
+
+ self.nxt_menu.AppendMenu("Firmware",submenu)
+
+ self.menubar.Append(self.nxt_menu, "&NXT")
+
+
+ self.SetMenuBar(menubar)
+
+
+ def FirmwareVersion(self,event):
+ versions={'Version 105':'105',
+ 'Version 107':'107',
+ 'Version 128':'128',
+ }
+
+ for menu in self.firmware_menus:
+ if menu.IsChecked():
+ self.firmware_version=versions[menu.Label]
+ self.UpdateConfig()
+
+
+
+ def Load(self,event=None):
+ dlg = FileDialog(self, 'Select a Program File',default_dir=os.getcwd(),wildcard='*.py',open=1)
+ try:
+ result = dlg.ShowModal()
+ if result == 'ok':
+ self.prog = dlg.GetPaths()[0]
+ self.ResetTitle()
+ finally:
+ dlg.Destroy()
+
+ def ResetTitle(self,event=None):
+ if self.prog:
+ junk,fname=os.path.split(self.prog)
+ s='PyNXC: %s' % fname
+ else:
+ s='PyNXC'
+
+ self.SetTitle(s)
+
+
+ def NXT_Info(self,event=None):
+ pass
+
+ def Quit(self,event=None):
+ self.Close()
+
+ def DoCmd(self,cmdlist):
+
+ S=self.textbox.GetValue()
+ S=S+"#-> "+" ".join(cmdlist)+"\n"
+ self.textbox.SetValue(S)
+
+ try:
+
+ if sys.platform=='win32':
+ output=subprocess.Popen(
+ cmdlist,stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,stderr=subprocess.PIPE)
+ else:
+ output=subprocess.Popen(
+ cmdlist,stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,stderr=subprocess.PIPE,close_fds=True)
+
+ try: # there might be non-ASCII chars in the output
+ S += output.stdout.read() + output.stderr.read()
+ except UnicodeDecodeError:
+ S += (output.stdout.read() + output.stderr.read()
+ ).decode('utf-8', 'replace')
+
+ self.textbox.SetValue(S)
+
+ except OSError:
+
+ s=sys.exc_info()
+ S=S+"Error with NXC Executable: "+str(s[1])
+ self.textbox.SetValue(S)
+ return
+
+
+
+ def Convert(self):
+ filename=self.prog
+
+# path,fname=os.path.split(filename)
+ root,ext=os.path.splitext(filename)
+
+ nxc_filename=root+".nxc"
+
+ S=self.textbox.GetValue()
+
+ S=S+"Writing %s..." % (nxc_filename)
+ self.textbox.SetValue(S)
+
+ python_to_nxc(filename,nxc_filename)
+
+
+ S=S+".done\n"
+ self.textbox.SetValue(S)
+
+ return nxc_filename
+
+
+ def OnlyConvert(self,event=None):
+ self.textbox.SetValue("")
+
+ if not self.prog:
+ self.Load()
+
+ if not self.prog:
+ dlg = MessageDialog(self, "Error","No Program File Selected")
+ dlg.ShowModal()
+ dlg.Destroy()
+ return
+
+ try:
+ nxc_filename=self.Convert()
+ except:
+ s=sys.exc_info()
+ str1="Error in "+self.prog +": "+str(s[1])
+ self.textbox.SetValue(str1)
+ return
+
+ def Compile(self,event=None):
+ self.textbox.SetValue("")
+
+ if not self.prog:
+ self.Load()
+
+ if not self.prog:
+ dlg = MessageDialog(self, "Error","No Program File Selected")
+ dlg.ShowModal()
+ dlg.Destroy()
+ return
+
+ try:
+ nxc_filename=self.Convert()
+ except:
+ s=sys.exc_info()
+ str1="Error in "+self.prog +": "+str(s[1])
+ self.textbox.SetValue(str1)
+ return
+
+
+ root,ext=os.path.splitext(nxc_filename)
+ rxe_filename=root+".rxe"
+
+
+
+ cmdlist=[self.nxc,nxc_filename," -v=%s" % self.firmware_version," -O=%s" % rxe_filename]
+
+ self.DoCmd(cmdlist)
+
+
+
+ def Download(self,event=None):
+
+ self.textbox.SetValue("")
+
+ if not self.prog:
+ self.Load()
+
+ if not self.prog:
+ dlg = MessageDialog(self, "Error","No Program File Selected")
+ dlg.ShowModal()
+ dlg.Destroy()
+ return
+
+ try:
+ nxc_filename=self.Convert()
+ except:
+ s=sys.exc_info()
+ str1="Error in "+self.prog +": "+str(s[1])
+ self.textbox.SetValue(str1)
+ return
+
+ flags=['-d','-S=usb','-v=%s' % self.firmware_version]
+ if self.bluetooth_menu.IsChecked():
+ flags.append('-BT')
+
+ root,ext=os.path.splitext(nxc_filename)
+ rxe_filename=root+".rxe"
+ cmdlist=[self.nxc]
+ cmdlist.extend(flags)
+ cmdlist.append(nxc_filename)
+
+ self.DoCmd(cmdlist)
+
+ root,ext=os.path.split(self.nxc)
+ nxtcom=os.path.join(root,'nxtcom_scripts/nxtcom')
+ print nxtcom
+ if os.path.exists(nxtcom):
+ print "Downloading...",
+ cmd='%s %s' % (nxtcom,rxe_filename)
+ a=os.system(cmd)
+ print "done."
+
+
+if __name__ == "__main__":
+
+
+ if len(sys.argv)<2: # no args given, launch gui
+ app = Application(MainFrame, title="PyNXC")
+ app.Run()
+ else:
+ sys.exit(main())
+