[cig-commits] r6113 - cs/babel/trunk/spike/Spike/Compiler
leif at geodynamics.org
leif at geodynamics.org
Sat Feb 24 18:38:55 PST 2007
Author: leif
Date: 2007-02-24 18:38:54 -0800 (Sat, 24 Feb 2007)
New Revision: 6113
Modified:
cs/babel/trunk/spike/Spike/Compiler/ExprNodes.py
cs/babel/trunk/spike/Spike/Compiler/Main.py
cs/babel/trunk/spike/Spike/Compiler/Nodes.py
cs/babel/trunk/spike/Spike/Compiler/Parsing.py
cs/babel/trunk/spike/Spike/Compiler/SpikeTypes.py
cs/babel/trunk/spike/Spike/Compiler/Symtab.py
cs/babel/trunk/spike/Spike/Compiler/gram.y
cs/babel/trunk/spike/Spike/Compiler/parser.pyx
cs/babel/trunk/spike/Spike/Compiler/scan.l
Log:
Wrote more robust code for declspecs. Added feedback loop for typedef
names. Record (file, line, column) in nodes. Added preliminary code
for C assignment/comma/conditional expressions. Reworked
SpikeFuncDefNode magic (but it's still not quite right; exported
Python names are now mangled). Implemented other assorted internal
improvements.
Modified: cs/babel/trunk/spike/Spike/Compiler/ExprNodes.py
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/ExprNodes.py 2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/ExprNodes.py 2007-02-25 02:38:54 UTC (rev 6113)
@@ -194,6 +194,11 @@
nodes.extend(item)
self.saved_subexpr_nodes = nodes
return self.saved_subexpr_nodes
+
+ def add_subexpr(self, expr):
+ # Called when an expression adds a subexpression late in the
+ # game.
+ self.saved_subexpr_nodes.append(expr)
def result_as(self, type = None):
# Return the result code cast to the specified C type.
@@ -209,6 +214,14 @@
return self.result_ctype or self.type
# ------------- Declaration Analysis ----------------
+
+ def analyse_declarations(self, env):
+ self.analyse_subexpr_declarations(env)
+
+ def analyse_subexpr_declarations(self, env):
+ for node in self.subexpr_nodes():
+ if node:
+ node.analyse_declarations(env)
def analyse_target_declaration(self, env):
error(self.pos, "Cannot assign to or delete this")
@@ -703,7 +716,12 @@
def analyse_types(self, env):
self.entry = env.lookup(self.name)
if not self.entry:
- self.entry = env.declare_builtin(self.name, self.pos)
+ if False:
+ # ...death, death, I say!
+ self.entry = env.declare_builtin(self.name, self.pos)
+ else:
+ error(self.pos, "'%s' undeclared" % self.name)
+ self.entry = env.declare_var(self.name, SpikeTypes.error_type, self.pos)
self.analyse_entry(env)
def analyse_entry(self, env):
@@ -734,7 +752,7 @@
def check_identifier_kind(self):
entry = self.entry
if not (entry.is_const or entry.is_variable
- or entry.is_builtin or entry.is_cfunction):
+ or entry.is_builtin or entry.is_cfunction or entry.is_spikefunction):
if self.entry.as_variable:
self.entry = self.entry.as_variable
else:
@@ -1226,6 +1244,7 @@
func_type = self.function_type()
if func_type.is_pyobject:
self.arg_tuple = TupleNode(self.pos, args = self.args)
+ self.add_subexpr(self.arg_tuple) # others?
self.args = None
self.arg_tuple.analyse_types(env)
self.type = py_object_type
@@ -1246,6 +1265,8 @@
# Return the type of the function being called, coercing a function
# pointer to a function if necessary.
func_type = self.function.type
+ if func_type.is_spikefunction:
+ func_type = self.function.entry.cfunc.type
if func_type.is_ptr:
func_type = func_type.base_type
return func_type
@@ -1321,7 +1342,7 @@
self.arg_tuple.py_result(),
self.result_code,
code.error_goto(self.pos)))
- elif func_type.is_cfunction:
+ elif func_type.is_cfunction or func_type.is_spikefunction:
exc_checks = []
if self.type.is_pyobject:
exc_checks.append("!%s" % self.result_code)
@@ -2627,7 +2648,7 @@
class CmpNode:
# Mixin class containing code common to PrimaryCmpNodes
# and CascadedCmpNodes.
-
+
def is_python_comparison(self):
return (self.has_python_operands()
or (self.cascade and self.cascade.is_python_comparison())
@@ -2786,7 +2807,11 @@
self.operand1.generate_disposal_code(code)
self.operand2.generate_disposal_code(code)
+ def analyse_declarations(self, env):
+ self.operand1.analyse_declarations(env)
+ self.operand2.analyse_declarations(env)
+
class CascadedCmpNode(Node, CmpNode):
# A CascadedCmpNode is not a complete expression node. It
# hangs off the side of another comparison node, shares
@@ -2846,7 +2871,90 @@
self.operand2.generate_disposal_code(code)
code.putln("}")
+ def analyse_declarations(self, env):
+ self.operand1.analyse_declarations(env)
+ self.operand2.analyse_declarations(env)
+
+class CAssignmentNode(ExprNode):
+ # C assignment expression
+ #
+ # operator string
+ # lhs ExprNode
+ # rhs ExprNode
+
+ subexprs = ['lhs', 'rhs']
+
+ def analyse_declarations(self, env):
+ self.lhs.analyse_target_declaration(env)
+ self.rhs.analyse_declarations(env)
+
+ def analyse_types(self, env):
+ self.rhs.analyse_types(env)
+ self.lhs.analyse_target_types(env)
+ self.rhs = self.rhs.coerce_to(self.lhs.type, env)
+ self.type = self.lhs.type # ???
+
+ def allocate_subexpr_temps(self, env):
+ self.rhs.allocate_temps(env)
+ self.lhs.allocate_target_temps(env)
+
+ def release_subexpr_temps(self, env):
+ self.lhs.release_target_temp(env)
+ self.rhs.release_temp(env)
+
+ def generate_result_code(self, code):
+ pass
+
+ def calculate_result_code(self):
+ if self.type.is_pyobject:
+ # Assignment generated by generate_assignment_code().
+ return None
+ return "(%s %s %s)" % (
+ self.lhs.result_code,
+ self.operator,
+ self.rhs.result_code)
+
+ def generate_subexpr_evaluation_code(self, code):
+ self.rhs.generate_evaluation_code(code)
+ if self.type.is_pyobject:
+ assert self.operator == "="
+ self.lhs.generate_assignment_code(self.rhs, code)
+ else:
+ self.lhs.generate_evaluation_code(code)
+
+ def generate_disposal_code(self, code):
+ if self.type.is_pyobject:
+ # ??? Already handled by generate_assignment_code()? I
+ # don't understand this very well yet...
+ pass
+ else:
+ ExprNode.generate_disposal_code(self, code)
+ return
+
+
+class CommaNode(ExprNode):
+ # C ',' expression
+ #
+ # lhs ExprNode
+ # rhs ExprNode
+
+ subexprs = ['lhs', 'rhs']
+
+ def analyse_types(self, env):
+ self.lhs.analyse_types(env)
+ self.rhs.analyse_types(env)
+ self.type = self.rhs.type
+
+ def generate_result_code(self, code):
+ pass
+
+ def calculate_result_code(self):
+ return "(%s, %s)" % (
+ self.lhs.result_code,
+ self.rhs.result_code)
+
+
binop_node_classes = {
"or": BoolBinopNode,
"and": BoolBinopNode,
@@ -2871,8 +2979,66 @@
operand1 = operand1,
operand2 = operand2)
+
#-------------------------------------------------------------------
#
+# Trinary operator nodes
+#
+#-------------------------------------------------------------------
+
+class ConditionalNode(ExprNode):
+ # "cond ? expr1 : expr2" conditional expression
+ #
+ # condition ExprNode
+ # if_expr ExprNode
+ # else_expr ExprNode
+
+ subexprs = ['condition', 'if_expr', 'else_expr']
+
+ def generate_result_code(self, code):
+ pass
+
+ # based on BinopNode
+
+ def analyse_types(self, env):
+ self.condition.analyse_types(env)
+ self.if_expr.analyse_types(env)
+ self.else_expr.analyse_types(env)
+ self.analyse_c_operation(env)
+
+ def check_const(self):
+ self.condition.check_const()
+ self.if_expr.check_const()
+ self.else_expr.check_const()
+
+ # based on NumBinopNode
+
+ def analyse_c_operation(self, env):
+ type1 = self.if_expr.type
+ type2 = self.else_expr.type
+ self.type = self.compute_c_result_type(type1, type2)
+ if not self.type:
+ self.type_error()
+
+ def compute_c_result_type(self, type1, type2):
+ if self.c_types_okay(type1, type2):
+ return SpikeTypes.widest_numeric_type(type1, type2)
+ else:
+ return None
+
+ def c_types_okay(self, type1, type2):
+ return type1.is_numeric and type2.is_numeric
+
+ def calculate_result_code(self):
+ return "(%s ? %s : %s)" % (
+ self.condition.result_code,
+ self.if_expr.result_code,
+ self.else_expr.result_code)
+
+
+
+#-------------------------------------------------------------------
+#
# Coercion nodes
#
# Coercion nodes are special in that they are created during
Modified: cs/babel/trunk/spike/Spike/Compiler/Main.py
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/Main.py 2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/Main.py 2007-02-25 02:38:54 UTC (rev 6113)
@@ -146,10 +146,8 @@
def parse(self, source_filename, type_names, pxd):
import parser
import Nodes
- stats = parser.parse(source_filename)
initial_pos = (source_filename, 1, 0)
- pos = initial_pos
- body = Nodes.StatListNode(pos, stats = stats)
+ body = parser.parse(source_filename, initial_pos)
tree = Nodes.ModuleNode(initial_pos, doc = None, body = body)
return tree
@@ -289,6 +287,17 @@
#------------------------------------------------------------------------
def main(command_line = 0):
+ try:
+ import IPython.ultraTB
+ except ImportError:
+ pass
+ else:
+ sys.excepthook = IPython.ultraTB.FormattedTB(
+ mode = "Verbose",
+ color_scheme = "Linux",
+ call_pdb = False
+ )
+
args = sys.argv[1:]
any_failures = 0
if command_line:
Modified: cs/babel/trunk/spike/Spike/Compiler/Nodes.py
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/Nodes.py 2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/Nodes.py 2007-02-25 02:38:54 UTC (rev 6113)
@@ -106,13 +106,22 @@
self.body.analyse_declarations(env)
def process_implementation(self, env, result):
+ self.declare_builtins(env)
self.analyse_declarations(env)
env.check_c_classes()
self.body.analyse_expressions(env)
env.return_type = SpikeTypes.c_void_type
self.generate_c_code(env, result)
self.generate_h_code(env, result)
-
+
+ def declare_builtins(self, env):
+ # Declare various built-in Python types for easy access from
+ # Spike code.
+ env.declare_builtin("dict", self.pos)
+ env.declare_builtin("list", self.pos)
+ env.declare_builtin("str", self.pos)
+ env.declare_builtin("tuple", self.pos)
+
def generate_h_code(self, env, result):
public_vars_and_funcs = []
public_extension_types = []
@@ -1445,7 +1454,9 @@
type = SpikeTypes.c_ptr_type(type.base_type)
# Catch attempted C-style func(void) decl
if type.is_void:
- error(arg_node.pos, "Function argument cannot be void")
+ if len(self.args) > 1:
+ error(arg_node.pos, "`void' in parameter list must be the entire list")
+ continue
func_type_args.append(
SpikeTypes.CFuncTypeArg(name, type, arg_node.pos))
if arg_node.default:
@@ -1652,17 +1663,18 @@
class CTypeDefNode(StatNode):
- # base_type CBaseTypeNode
- # declarator CDeclaratorNode
+ # base_type CBaseTypeNode
+ # declarators [CDeclaratorNode]
def analyse_declarations(self, env):
- base = self.base_type.analyse(env)
- name_declarator, type = self.declarator.analyse(base, env)
- name = name_declarator.name
- cname = name_declarator.cname
- if env.in_cinclude:
- type = CTypedefType(cname or name, type)
- env.declare_type(name, type, self.pos, cname = cname)
+ for declarator in self.declarators:
+ base = self.base_type.analyse(env)
+ name_declarator, type = declarator.analyse(base, env)
+ name = name_declarator.name
+ cname = name_declarator.cname
+ if env.in_cinclude:
+ type = CTypedefType(cname or name, type)
+ env.declare_type(name, type, self.pos, cname = cname)
def analyse_expressions(self, env):
pass
@@ -1671,6 +1683,134 @@
pass
+class DeclSpecs:
+
+ def __init__(self):
+ self.pos = None
+ self.specifiers = []
+
+ def add(self, token):
+ specifier, pos = token
+ if self.pos is None:
+ self.pos = pos
+ self.specifiers.insert(0, specifier)
+
+ def analyse(self):
+ # defaults
+ storage = 'auto' # ?
+ name = 'int'
+ signed = 1
+ longness = 0
+ # counts
+ signed_specs = 0
+ unsigned_specs = 0
+ short_specs = 0
+ long_specs = 0
+ type_specs = 0
+ storage_specs = 0
+ # loop
+ for specifier in self.specifiers:
+ if specifier == 'signed':
+ signed = 1
+ signed_specs += 1
+ elif specifier == 'unsigned':
+ signed = 0
+ unsigned_specs += 1
+ elif specifier == 'short':
+ longness = -1
+ short_specs += 1
+ elif specifier == 'long':
+ longness += 1 # for "long long"
+ long_specs += 1
+ elif specifier in ['char', 'int', 'float', 'double', 'void', 'obj']:
+ name = specifier
+ type_specs += 1
+ elif specifier in ['typedef', 'extern', 'static', 'auto', 'register']:
+ storage = specifier
+ storage_specs += 1
+ # error check
+ errors = 0
+ if signed_specs and unsigned_specs:
+ error(self.pos, "both signed and unsigned specified")
+ errors += 1
+ if short_specs and long_specs:
+ error(self.pos, "both long and short specified")
+ errors += 1
+ if type_specs > 1:
+ error(self.pos, "multiple data types specified")
+ errors += 1
+ if storage_specs > 1:
+ error(self.pos, "multiple storage classes specified")
+ errors += 1
+ if errors:
+ pass #?
+ # construct base type
+ base_type = CSimpleBaseTypeNode(
+ self.pos,
+ name = name,
+ module_path = [],
+ is_basic_c_type = 1,
+ signed = signed,
+ longness = longness,
+ is_self_arg = 0
+ )
+ return storage, base_type
+
+ def declaration(self, declarators):
+ import parser
+ storage, base_type = self.analyse()
+ # construct decl
+ decl = None
+ if storage == 'typedef':
+ decl = CTypeDefNode(self.pos,
+ base_type = base_type,
+ declarators = declarators)
+ for declarator in declarators:
+ name_decl = declarator
+ while not isinstance(name_decl, CNameDeclaratorNode):
+ name_decl = name_decl.base
+ parser.declare_type_name(name_decl.name)
+ elif storage in ['auto', 'static', 'register', 'extern']:
+ visibility = 'private'
+ if storage == 'extern':
+ visibility = 'extern'
+ decl = CVarDefNode(self.pos,
+ visibility = visibility,
+ base_type = base_type,
+ declarators = declarators)
+ else:
+ error(self.pos, "unimplemented storage class `%s'" % storage)
+ ret = StatListNode(self.pos, stats = [decl])
+ return ret
+
+ def function_definition(self, declarator, function_body):
+ storage, base_type = self.analyse()
+ stats = SpikeFuncDefNode.new_spike_func(
+ self.pos,
+ visibility = 'public',
+ base_type = base_type,
+ declarator = declarator,
+ body = function_body
+ )
+ ret = StatListNode(self.pos, stats = stats)
+ return ret
+
+ def analyse_type(self):
+ # Storage class specifiers are syntactically impossible.
+ _, base_type = self.analyse()
+ return base_type
+
+ def analyse_type_modifiers(self):
+ errors = 0
+ for specifier in self.specifiers:
+ if not specifier in ['const', 'volatile']:
+ errors += 1
+ if errors:
+ # It is probably possible to disallow this syntactically.
+ error(self.pos, "only type modifiers are allowed here")
+ return None # NYI
+
+
class FuncDefNode(StatNode, BlockNode):
# Base class for function definition nodes.
#
@@ -1995,10 +2135,11 @@
desc, self.name, len(self.args), expected_str))
def declare_pyfunction(self, env):
- self.entry = env.declare_pyfunction(self.name, self.pos)
+ cname = Naming.func_prefix + env.scope_prefix + self.name
+ # Declare as 'cname', since the SpikeFuncDefNode is declared as 'self.name'.
+ self.entry = env.declare_pyfunction(cname, self.pos)
self.entry.doc = self.doc
- self.entry.func_cname = \
- Naming.func_prefix + env.scope_prefix + self.name
+ self.entry.func_cname = cname
self.entry.doc_cname = \
Naming.funcdoc_prefix + env.scope_prefix + self.name
self.entry.pymethdef_cname = \
@@ -2295,99 +2436,81 @@
return 1
-class SpikeFuncDefNode(DefNode):
+class SpikeFuncDefNode(StatNode):
# A Spike function definition.
- def __init__(self, pos, visibility, base_type, declarator, body):
+ def new_spike_func(cls, pos, visibility, base_type, declarator, body):
import ExprNodes
args = []
call_args = []
- for arg_decl in declarator.args:
+ fdecl = declarator
+ while not isinstance(fdecl, CFuncDeclaratorNode):
+ fdecl = fdecl.base
+ for arg_decl in fdecl.args:
arg = CArgDeclNode(arg_decl.pos,
base_type = arg_decl.base_type,
declarator = arg_decl.declarator,
not_none = 0,
default = None)
args.append(arg)
- call_arg = ExprNodes.NameNode(arg_decl.pos, name = arg_decl.declarator.name)
+ name_decl = arg_decl.declarator
+ while not isinstance(name_decl, CNameDeclaratorNode):
+ name_decl = name_decl.base
+ call_arg = ExprNodes.NameNode(arg_decl.pos, name = name_decl.name)
call_args.append(call_arg)
- DefNode.__init__(self,
- pos,
- name = declarator.base.name,
+ name = fdecl.base.name
+ # The C function bears the original name in the generated code...
+ fdecl.base.cname = name
+ # ...but is mangled internally to avoid conflict with the Spike function.
+ cname = "__spike_cf_" + name
+ fdecl.base.name = cname
+ cfunc = CFuncDefNode(pos,
+ visibility = visibility,
+ base_type = base_type,
+ declarator = declarator,
+ body = body)
+ pybody = cls.construct_body(pos, call_args, base_type, declarator, fdecl)
+ pyfunc = DefNode(pos,
+ name = name,
args = args,
star_arg = None,
starstar_arg = None,
doc = None,
- body = None)
- declarator.base.name = "__spike_cf_" + declarator.base.name
- self.cfunc = CFuncDefNode(pos,
- visibility = visibility,
- base_type = base_type,
- declarator = declarator,
- body = body)
- self.construct_body(call_args, base_type)
+ body = pybody)
+ func = cls(pos, name = name, cfunc = cfunc, pyfunc = pyfunc, cname = name)
+ return [cfunc, pyfunc, func]
+ new_spike_func = classmethod(new_spike_func)
- def construct_body(self, call_args, base_type):
+ def construct_body(cls, pos, call_args, base_type, declarator, fdecl):
import ExprNodes
- # NYI: 'base_type' is not correct for the return type.
- ret_decl = CVarDefNode(self.pos, visibility = 'private', base_type = base_type,
- declarators = [CNameDeclaratorNode(self.pos, name = "ret", cname = None)])
- name = self.cfunc.declarator.base.name
- function = ExprNodes.NameNode(self.pos, name = name)
- expr = ExprNodes.SimpleCallNode(self.pos,
+ from copy import copy
+ stats = []
+ name = fdecl.base.name
+ function = ExprNodes.NameNode(pos, name = name)
+ expr = ExprNodes.SimpleCallNode(pos,
function = function,
args = call_args)
- ret = ExprNodes.NameNode(self.pos, name = "ret")
- stmt1 = SingleAssignmentNode(self.pos, lhs = ret, rhs = expr)
- ret = ExprNodes.NameNode(self.pos, name = "ret")
- stmt2 = ReturnStatNode(self.pos, value = ret)
- self.body = StatListNode(self.pos, stats = [ret_decl, stmt1, stmt2])
- return
+ if base_type.name == 'void':
+ stmt = ExprStatNode(pos, expr = expr)
+ stats.append(stmt)
+ else:
+ stmt = ReturnStatNode(pos, value = expr)
+ stats.append(stmt)
+ body = StatListNode(pos, stats = stats)
+ return body
+ construct_body = classmethod(construct_body)
- #
- # BlockNode protocol
- #
-
- def generate_const_definitions(self, env, code):
- self.cfunc.generate_const_definitions(env, code)
- DefNode.generate_const_definitions(self, env, code)
-
- def generate_interned_name_decls(self, env, code):
- self.cfunc.generate_interned_name_decls(env, code)
- DefNode.generate_interned_name_decls(self, env, code)
-
- def generate_py_string_decls(self, env, code):
- self.cfunc.generate_py_string_decls(env, code)
- DefNode.generate_py_string_decls(self, env, code)
+ def analyse_declarations(self, env):
+ self.entry = env.declare_spikefunction(self.name, self.cname, self.pos,
+ self.cfunc, self.pyfunc)
+
+ def analyse_expressions(self, env):
+ pass
- #
- # StatNode protocol
-
- def generate_function_definitions(self, env, code):
- self.cfunc.generate_function_definitions(env, code)
- DefNode.generate_function_definitions(self, env, code)
-
def generate_execution_code(self, code):
- self.cfunc.generate_execution_code(code)
- DefNode.generate_execution_code(self, code)
+ pass
- #
- # Node protocol
- #
-
- def analyse_declarations(self, env):
- self.cfunc.analyse_declarations(env)
- DefNode.analyse_declarations(self, env)
- def analyse_expressions(self, env):
- self.cfunc.analyse_expressions(env)
- DefNode.analyse_expressions(self, env)
-
- def generate_code(self, code):
- self.cfunc.generate_code(code)
- DefNode.generate_code(self, code)
-
-
class PyClassDefNode(StatNode, BlockNode):
# A Python class definition.
#
@@ -2578,6 +2701,10 @@
#
# expr ExprNode
+ def analyse_declarations(self, env):
+ # for CAssignmentNode
+ self.expr.analyse_declarations(env)
+
def analyse_expressions(self, env):
self.expr.analyse_expressions(env)
self.expr.release_temp(env)
Modified: cs/babel/trunk/spike/Spike/Compiler/Parsing.py
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/Parsing.py 2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/Parsing.py 2007-02-25 02:38:54 UTC (rev 6113)
@@ -1611,7 +1611,7 @@
declarator = p_c_declarator(s, is_type = 1)
s.expect_newline("Syntax error in ctypedef statement")
return Nodes.CTypeDefNode(pos,
- base_type = base_type, declarator = declarator)
+ base_type = base_type, declarators = [declarator])
def p_def_statement(s):
# s.sy == 'def'
Modified: cs/babel/trunk/spike/Spike/Compiler/SpikeTypes.py
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/SpikeTypes.py 2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/SpikeTypes.py 2007-02-25 02:38:54 UTC (rev 6113)
@@ -19,6 +19,7 @@
# is_ptr boolean Is a C pointer type
# is_null_ptr boolean Is the type of NULL
# is_cfunction boolean Is a C function type
+ # is_spikefunction boolean Is a Spike function type
# is_struct_or_union boolean Is a C struct or union type
# is_enum boolean Is a C enum type
# is_string boolean Is a C char * type
@@ -64,6 +65,7 @@
is_ptr = 0
is_null_ptr = 0
is_cfunction = 0
+ is_spikefunction = 0
is_struct_or_union = 0
is_enum = 0
is_string = 0
@@ -423,6 +425,9 @@
is_ptr = 1
default_value = 0
+ to_py_function = "PyCObject_FromVoidPtr"
+ from_py_function = "PyCObject_AsVoidPtr"
+ parsetuple_format = "???"
def __init__(self, base_type):
self.base_type = base_type
@@ -567,6 +572,20 @@
return self.type.declaration_code(self.cname, for_display)
+class SpikeFuncType(SpikeType):
+
+ is_spikefunction = 1
+
+ def __repr__(self):
+ return "SpikeFuncType"
+
+ def declaration_code(self, entity_code,
+ for_display = 0, dll_linkage = None, pyrex = 0):
+ if for_display:
+ return "SpikeFuncType"
+ return ""
+
+
class CStructOrUnionType(CType):
# name string
# cname string
@@ -690,6 +709,8 @@
py_object_type = PyObjectType()
+spike_function_type = SpikeFuncType()
+
c_void_type = CVoidType()
c_void_ptr_type = CPtrType(c_void_type)
c_void_ptr_ptr_type = CPtrType(c_void_ptr_type)
Modified: cs/babel/trunk/spike/Spike/Compiler/Symtab.py
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/Symtab.py 2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/Symtab.py 2007-02-25 02:38:54 UTC (rev 6113)
@@ -8,6 +8,7 @@
import Naming
from SpikeTypes import c_int_type, \
py_object_type, c_char_array_type, \
+ spike_function_type, \
CEnumType, CStructOrUnionType, PyExtensionType
from TypeSlots import \
pyfunction_signature, pymethod_signature, \
@@ -31,6 +32,7 @@
# class construction
# is_variable boolean Is a variable
# is_cfunction boolean Is a C function
+ # is_spikefunction boolean Is a Spike function
# is_cmethod boolean Is a C method of an extension type
# is_type boolean Is a type definition
# is_const boolean Is a constant
@@ -108,6 +110,7 @@
# sue_entries [Entry] Struct/union/enum entries
# arg_entries [Entry] Function argument entries
# var_entries [Entry] User-defined variable entries
+ # spikefunc_entries [Entry] Spike function entries
# pyfunc_entries [Entry] Python function entries
# cfunc_entries [Entry] C function entries
# c_class_entries [Entry] All extension type entries
@@ -149,6 +152,7 @@
self.sue_entries = []
self.arg_entries = []
self.var_entries = []
+ self.spikefunc_entries = []
self.pyfunc_entries = []
self.cfunc_entries = []
self.c_class_entries = []
@@ -290,6 +294,15 @@
def declare_builtin(self, name, pos):
return self.outer_scope.declare_builtin(name, pos)
+ def declare_spikefunction(self, name, cname, pos, cfunc, pyfunc):
+ # Add an entry for a Spike function.
+ entry = self.declare(name, cname, spike_function_type, pos)
+ entry.is_spikefunction = 1
+ entry.cfunc = cfunc
+ entry.pyfunc = pyfunc
+ self.spikefunc_entries.append(entry)
+ return entry
+
def declare_pyfunction(self, name, pos):
# Add an entry for a Python function.
entry = self.declare_var(name, py_object_type, pos)
Modified: cs/babel/trunk/spike/Spike/Compiler/gram.y
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/gram.y 2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/gram.y 2007-02-25 02:38:54 UTC (rev 6113)
@@ -9,6 +9,8 @@
%}
+%error-verbose
+
%token IDENTIFIER
%token LITERAL_INT LITERAL_FLOAT LITERAL_CHAR LITERAL_STRING
%token SIZEOF
@@ -38,13 +40,13 @@
postfix_expr
: primary_expr
- | postfix_expr '[' expr ']' { CHECK($$ = index_expr($1, $3)); }
- | postfix_expr '(' ')' { CHECK($$ = call_expr($1, empty_list())); }
- | postfix_expr '(' argument_expr_list ')' { CHECK($$ = call_expr($1, $3)); }
- | postfix_expr '.' identifier { CHECK($$ = attr_expr($1, $3)); }
- | postfix_expr PTR_OP identifier { CHECK($$ = attr_expr($1, $3)); }
- | postfix_expr INC_OP { CHECK($$ = postfix_inc_expr($1)); }
- | postfix_expr DEC_OP { CHECK($$ = postfix_dec_expr($1)); }
+ | postfix_expr '[' expr ']' { CHECK($$ = index_expr($2, $1, $3)); }
+ | postfix_expr '(' ')' { CHECK($$ = call_expr($2, $1, empty_list())); }
+ | postfix_expr '(' argument_expr_list ')' { CHECK($$ = call_expr($2, $1, $3)); }
+ | postfix_expr '.' identifier { CHECK($$ = attr_expr($2, $1, $3)); }
+ | postfix_expr PTR_OP identifier { CHECK($$ = attr_expr($2, $1, $3)); }
+ | postfix_expr INC_OP { CHECK($$ = postfix_inc_expr($2, $1)); }
+ | postfix_expr DEC_OP { CHECK($$ = postfix_dec_expr($2, $1)); }
;
argument_expr_list
@@ -55,92 +57,92 @@
unary_expr
: postfix_expr
| unary_operator cast_expr { CHECK($$ = unary_op_expr($1, $2)); }
- | SIZEOF unary_expr { CHECK($$ = sizeof_var_expr($2)); }
- | SIZEOF '(' type_name ')' { CHECK($$ = sizeof_type_expr($3)); }
+ | SIZEOF unary_expr { CHECK($$ = sizeof_var_expr($1, $2)); }
+ | SIZEOF '(' type_name ')' { CHECK($$ = sizeof_type_expr($1, $3)); }
;
unary_operator
- : '&' { CHECK($$ = unary_address_of()) }
- | '*' { CHECK($$ = unary_indirection()) }
- | '+' { CHECK($$ = unary_plus()) }
- | '-' { CHECK($$ = unary_minus()) }
- | '~' { CHECK($$ = unary_bitwise_negation()) }
- | '!' { CHECK($$ = unary_not()) }
- | INC_OP { CHECK($$ = unary_prefix_inc()) }
- | DEC_OP { CHECK($$ = unary_prefix_dec()) }
+ : '&'
+ | '*'
+ | '+'
+ | '-'
+ | '~'
+ | '!'
+ | INC_OP
+ | DEC_OP
;
cast_expr
: unary_expr
- | '(' type_name ')' cast_expr { CHECK($$ = cast_expr($2, $4)); }
+ | '(' type_name ')' cast_expr { CHECK($$ = cast_expr($1, $2, $4)); }
;
multiplicative_expr
: cast_expr
- | multiplicative_expr '*' cast_expr { CHECK($$ = mul_expr($1, $3)); }
- | multiplicative_expr '/' cast_expr { CHECK($$ = div_expr($1, $3)); }
- | multiplicative_expr '%' cast_expr { CHECK($$ = mod_expr($1, $3)); }
+ | multiplicative_expr '*' cast_expr { CHECK($$ = binary_expr($2, $1, $3)); }
+ | multiplicative_expr '/' cast_expr { CHECK($$ = binary_expr($2, $1, $3)); }
+ | multiplicative_expr '%' cast_expr { CHECK($$ = binary_expr($2, $1, $3)); }
;
additive_expr
: multiplicative_expr
- | additive_expr '+' multiplicative_expr { CHECK($$ = add_expr($1, $3)); }
- | additive_expr '-' multiplicative_expr { CHECK($$ = sub_expr($1, $3)); }
+ | additive_expr '+' multiplicative_expr { CHECK($$ = binary_expr($2, $1, $3)); }
+ | additive_expr '-' multiplicative_expr { CHECK($$ = binary_expr($2, $1, $3)); }
;
shift_expr
: additive_expr
- | shift_expr LEFT_OP additive_expr { CHECK($$ = shift_left_expr($1, $3)); }
- | shift_expr RIGHT_OP additive_expr { CHECK($$ = shift_right_expr($1, $3)); }
+ | shift_expr LEFT_OP additive_expr { CHECK($$ = binary_expr($2, $1, $3)); }
+ | shift_expr RIGHT_OP additive_expr { CHECK($$ = binary_expr($2, $1, $3)); }
;
relational_expr
: shift_expr
- | relational_expr '<' shift_expr { CHECK($$ = l_expr($1, $3)); }
- | relational_expr '>' shift_expr { CHECK($$ = g_expr($1, $3)); }
- | relational_expr LE_OP shift_expr { CHECK($$ = le_expr($1, $3)); }
- | relational_expr GE_OP shift_expr { CHECK($$ = ge_expr($1, $3)); }
+ | relational_expr '<' shift_expr { CHECK($$ = binary_expr($2, $1, $3)); }
+ | relational_expr '>' shift_expr { CHECK($$ = binary_expr($2, $1, $3)); }
+ | relational_expr LE_OP shift_expr { CHECK($$ = binary_expr($2, $1, $3)); }
+ | relational_expr GE_OP shift_expr { CHECK($$ = binary_expr($2, $1, $3)); }
;
equality_expr
: relational_expr
- | equality_expr EQ_OP relational_expr { CHECK($$ = eq_expr($1, $3)); }
- | equality_expr NE_OP relational_expr { CHECK($$ = ne_expr($1, $3)); }
+ | equality_expr EQ_OP relational_expr { CHECK($$ = binary_expr($2, $1, $3)); }
+ | equality_expr NE_OP relational_expr { CHECK($$ = binary_expr($2, $1, $3)); }
;
and_expr
: equality_expr
- | and_expr '&' equality_expr { CHECK($$ = and_expr($1, $3)); }
+ | and_expr '&' equality_expr { CHECK($$ = binary_expr($2, $1, $3)); }
;
exclusive_or_expr
: and_expr
- | exclusive_or_expr '^' and_expr { CHECK($$ = xor_expr($1, $3)); }
+ | exclusive_or_expr '^' and_expr { CHECK($$ = binary_expr($2, $1, $3)); }
;
inclusive_or_expr
: exclusive_or_expr
- | inclusive_or_expr '|' exclusive_or_expr { CHECK($$ = or_expr($1, $3)); }
+ | inclusive_or_expr '|' exclusive_or_expr { CHECK($$ = binary_expr($2, $1, $3)); }
;
logical_and_expr
: inclusive_or_expr
- | logical_and_expr AND_OP inclusive_or_expr { CHECK($$ = logical_and_expr($1, $3)); }
+ | logical_and_expr AND_OP inclusive_or_expr { CHECK($$ = binary_expr($2, $1, $3)); }
;
logical_or_expr
: logical_and_expr
- | logical_or_expr OR_OP logical_and_expr { CHECK($$ = logical_or_expr($1, $3)); }
+ | logical_or_expr OR_OP logical_and_expr { CHECK($$ = binary_expr($2, $1, $3)); }
;
conditional_expr
: logical_or_expr
- | logical_or_expr '?' logical_or_expr ':' conditional_expr
+ | logical_or_expr '?' logical_or_expr ':' conditional_expr { CHECK($$ = conditional_expr($2, $1, $3, $5)); }
;
assignment_expr
: conditional_expr
- | unary_expr assignment_operator assignment_expr { CHECK($$ = assignment_expr(Py_None, $1, $3)); }
+ | unary_expr assignment_operator assignment_expr { CHECK($$ = assignment_expr($2, $1, $3)); }
;
assignment_operator
@@ -159,7 +161,7 @@
expr
: assignment_expr
- | expr ',' assignment_expr
+ | expr ',' assignment_expr { CHECK($$ = comma_expr($2, $1, $3)); }
;
constant_expr
@@ -172,10 +174,10 @@
;
declaration_specifiers
- : storage_class_specifier
- | storage_class_specifier declaration_specifiers
- | type_specifier
- | type_specifier declaration_specifiers
+ : storage_class_specifier { CHECK($$ = declaration_specifiers($1, Py_None)); }
+ | storage_class_specifier declaration_specifiers { CHECK($$ = declaration_specifiers($1, $2)); }
+ | type_specifier { CHECK($$ = declaration_specifiers($1, Py_None)); }
+ | type_specifier declaration_specifiers { CHECK($$ = declaration_specifiers($1, $2)); }
;
init_declarator_list
@@ -197,18 +199,18 @@
;
type_specifier
- : CHAR { CHECK($$ = char_type()); }
+ : CHAR
| SHORT
- | INT { CHECK($$ = int_type()); }
- | LONG { CHECK($$ = long_type()); }
- | SIGNED { CHECK($$ = signed_type()); }
- | UNSIGNED { CHECK($$ = unsigned_type()); }
- | FLOAT { CHECK($$ = float_type()); }
- | DOUBLE { CHECK($$ = double_type()); }
+ | INT
+ | LONG
+ | SIGNED
+ | UNSIGNED
+ | FLOAT
+ | DOUBLE
| CONST
| VOLATILE
- | VOID { CHECK($$ = void_type()); }
- | OBJ { CHECK($$ = obj_type()); }
+ | VOID
+ | OBJ
| struct_or_union_specifier
| enum_specifier
| TYPE_NAME
@@ -268,7 +270,7 @@
declarator2
: identifier { CHECK($$ = name_declarator($1)); }
- | '(' declarator ')' { CHECK($$ = $2); }
+ | '(' declarator ')' { $$ = $2; }
| declarator2 '[' ']' { CHECK($$ = array_declarator($1, Py_None)); }
| declarator2 '[' constant_expr ']' { CHECK($$ = array_declarator($1, $3)); }
| declarator2 '(' ')' { CHECK($$ = function_declarator($1, empty_list())); }
@@ -277,10 +279,10 @@
;
pointer
- : '*' { CHECK($$ = pointer(Py_None)); }
- | '*' type_specifier_list { CHECK($$ = pointer($2)); }
- | '*' pointer { CHECK($$ = pointer($2)); }
- | '*' type_specifier_list pointer { CHECK($$ = pointer($3)); /*???*/ }
+ : '*' { CHECK($$ = pointer($1, Py_None, Py_None)); }
+ | '*' type_specifier_list { CHECK($$ = pointer($1, $2, Py_None)); }
+ | '*' pointer { CHECK($$ = pointer($1, Py_None, $2)); }
+ | '*' type_specifier_list pointer { CHECK($$ = pointer($1, $2, $3)); }
;
type_specifier_list
@@ -363,10 +365,10 @@
;
compound_statement
- : '{' '}' { CHECK($$ = compound_statement(Py_None, Py_None)); }
- | '{' statement_list '}' { CHECK($$ = compound_statement(Py_None, $2)); }
- | '{' declaration_list '}' { CHECK($$ = compound_statement($2, Py_None)); }
- | '{' declaration_list statement_list '}' { CHECK($$ = compound_statement($2, $3)); }
+ : '{' '}' { CHECK($$ = compound_statement($1, Py_None, Py_None)); }
+ | '{' statement_list '}' { CHECK($$ = compound_statement($1, Py_None, $2)); }
+ | '{' declaration_list '}' { CHECK($$ = compound_statement($1, $2, Py_None)); }
+ | '{' declaration_list statement_list '}' { CHECK($$ = compound_statement($1, $2, $3)); }
;
declaration_list
@@ -380,18 +382,19 @@
;
expression_statement
- : ';' { CHECK($$ = pass_statement()); }
+ : ';' { CHECK($$ = pass_statement($1)); }
| expr ';' { CHECK($$ = expression_statement($1)); }
+ | error ';' { yyerrok; }
;
selection_statement
- : IF '(' expr ')' statement { CHECK($$ = if_statement($3, $5, Py_None)); }
- | IF '(' expr ')' statement ELSE statement { CHECK($$ = if_statement($3, $5, $7)); }
+ : IF '(' expr ')' statement { CHECK($$ = if_statement($1, $3, $5, Py_None)); }
+ | IF '(' expr ')' statement ELSE statement { CHECK($$ = if_statement($1, $3, $5, $7)); }
| SWITCH '(' expr ')' statement
;
iteration_statement
- : WHILE '(' expr ')' statement { CHECK($$ = while_statement($3, $5)); }
+ : WHILE '(' expr ')' statement { CHECK($$ = while_statement($1, $3, $5)); }
| DO statement WHILE '(' expr ')' ';'
| FOR '(' ';' ';' ')' statement
| FOR '(' ';' ';' expr ')' statement
@@ -407,8 +410,8 @@
: GOTO identifier ';'
| CONTINUE ';'
| BREAK ';'
- | RETURN ';' { CHECK($$ = return_statement(Py_None)); }
- | RETURN expr ';' { CHECK($$ = return_statement($2)); }
+ | RETURN ';' { CHECK($$ = return_statement($1, Py_None)); }
+ | RETURN expr ';' { CHECK($$ = return_statement($1, $2)); }
;
file
@@ -418,12 +421,12 @@
external_definition
: function_definition
- | declaration { $$ = Py_None; }
+ | declaration
;
function_definition
- : declarator function_body { CHECK($$ = function_definition(Py_None, $1, $2)); }
- | declaration_specifiers declarator function_body { CHECK($$ = function_definition($1, $2, $3)); }
+ : declarator { push_scope(); } function_body { pop_scope(); CHECK($$ = function_definition(Py_None, $1, $3)); }
+ | declaration_specifiers declarator { push_scope(); } function_body { pop_scope(); CHECK($$ = function_definition($1, $2, $4)); }
;
function_body
@@ -436,14 +439,4 @@
;
%%
-#include <stdio.h>
-
-extern char yytext[];
-extern int column;
-
-yyerror(s)
-char *s;
-{
- fflush(stdout);
- printf("\n%*s\n%*s\n", column, "^", column, s);
-}
+/* end of file */
Modified: cs/babel/trunk/spike/Spike/Compiler/parser.pyx
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/parser.pyx 2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/parser.pyx 2007-02-25 02:38:54 UTC (rev 6113)
@@ -6,16 +6,23 @@
FILE *yyin
int yyparse()
-theDefList = list()
+from Spike.Compiler.Nodes import \
+ StatListNode
-def parse(char *filename):
+theDefList = None
+currentFilename = None
+
+def parse(filename, initial_pos):
cdef int status
- global yyin
+ global yyin, currentFilename, theDefList
+ currentFilename = filename
yyin = fopen(filename, "r")
+ theDefList = StatListNode(initial_pos, stats = [])
+ push_scope() # global scope
status = yyparse()
- if (status != 0):
- raise RuntimeError("parse error")
+ #if (status != 0):
+ # raise RuntimeError("parse error")
return theDefList
#------------------------------------------------------------------------
@@ -25,8 +32,7 @@
#------------------------------------------------------------------------
from Spike.Compiler.Nodes import \
- CSimpleBaseTypeNode, \
- SpikeFuncDefNode
+ CSimpleBaseTypeNode
from Spike.Compiler.ExprNodes import \
AttributeNode, \
@@ -42,43 +48,51 @@
SizeofVarNode, \
StringNode
-pos = ("nowhere.pyx", 1, 0) # NYI
-
# expressions -- primary
-cdef public object name_expr(object name):
+cdef public object name_expr(object token):
+ name, pos = token
return NameNode(pos, name = name)
-cdef public object literal_int_expr(object value):
+cdef public object literal_int_expr(object token):
+ value, pos = token
return IntNode(pos, value = value)
-cdef public object literal_float_expr(object value):
+cdef public object literal_float_expr(object token):
+ value, pos = token
return FloatNode(pos, value = value)
-cdef public object literal_char_expr(object value):
+cdef public object literal_char_expr(object token):
+ value, pos = token
return CharNode(pos, value = value)
-cdef public object literal_string_expr(object value):
+cdef public object literal_string_expr(object token):
+ value, pos = token
return StringNode(pos, value = value)
# expressions -- postfix
-cdef public object index_expr(object base, object index):
+cdef public object index_expr(object operator, object base, object index):
+ _, pos = operator # 'operator' is the '[' token
return IndexNode(pos, base = base, index = index)
-cdef public object call_expr(object function, object args):
+cdef public object call_expr(object operator, object function, object args):
+ _, pos = operator # 'operator' is the '(' token
return SimpleCallNode(pos, function = function, args = args)
-cdef public object attr_expr(object obj, object attribute):
- return AttributeNode(pos, obj = obj, attribute = attribute)
+cdef public object attr_expr(object operator, object obj, object attribute):
+ _, pos = operator
+ return AttributeNode(pos, obj = obj, attribute = attribute[0])
-cdef public object postfix_inc_expr(object operand):
- return PostfixIncNode(pos, operator = '++', operand = operand)
+cdef public object postfix_inc_expr(object token, object operand):
+ operator, pos = token
+ return PostfixIncNode(pos, operator = operator, operand = operand)
-cdef public object postfix_dec_expr(object operand):
- return PostfixDecNode(pos, operator = '--', operand = operand)
+cdef public object postfix_dec_expr(object token, object operand):
+ operator, pos = token
+ return PostfixDecNode(pos, operator = operator, operand = operand)
cdef public object argument_expr_list(object argument_expr_list, object assignment_expr):
if argument_expr_list is None:
@@ -89,20 +103,45 @@
# expressions -- unary
-cdef public object unary_op_expr(object operator, object operand):
- cls, operator = operator
+from Spike.Compiler.ExprNodes import \
+ AmpersandNode, \
+ IndirectionNode, \
+ UnaryPlusNode, \
+ UnaryMinusNode, \
+ TildeNode, \
+ NotNode, \
+ PrefixIncNode, \
+ PrefixDecNode
+
+unop_node_classes = {
+ '&': AmpersandNode,
+ '*': IndirectionNode,
+ '+': UnaryPlusNode,
+ '-': UnaryMinusNode,
+ '~': TildeNode,
+ '!': NotNode,
+ '++': PrefixIncNode,
+ '--': PrefixDecNode,
+}
+
+cdef public object unary_op_expr(object token, object operand):
+ operator, pos = token
+ cls = unop_node_classes[operator]
return cls(pos, operator = operator, operand = operand)
-cdef public object sizeof_var_expr(object operand):
+cdef public object sizeof_var_expr(object keyword, object operand):
+ _, pos = keyword
return SizeofVarNode(pos, operand = operand)
-cdef public object sizeof_type_expr(object type_name):
+cdef public object sizeof_type_expr(object keyword, object type_name):
+ _, pos = keyword
base_type, declarator = type_name
return SizeofTypeNode(pos, base_type = base_type, declarator = declarator)
-cdef public object cast_expr(object type_name, object operand):
+cdef public object cast_expr(object lparen, object type_name, object operand):
+ _, pos = lparen
base_type, declarator = type_name
- return TypecastNode(base_type = base_type, declarator = declarator, operand = operand)
+ return TypecastNode(pos, base_type = base_type, declarator = declarator, operand = operand)
# expressions -- binary
@@ -115,110 +154,66 @@
NumBinopNode, \
IntBinopNode, \
BoolBinopNode, \
- PrimaryCmpNode
+ PrimaryCmpNode, \
+ ConditionalNode, \
+ CAssignmentNode, \
+ CommaNode
-from Spike.Compiler.Nodes import \
- SingleAssignmentNode
+binop_node_classes = {
+ '*': MulNode,
+ '/': NumBinopNode,
+ '%': ModNode,
+ '+': AddNode,
+ '-': SubNode,
+ '<<': IntBinopNode,
+ '>>': IntBinopNode,
+ '<': PrimaryCmpNode,
+ '>': PrimaryCmpNode,
+ '<=': PrimaryCmpNode,
+ '>=': PrimaryCmpNode,
+ '==': PrimaryCmpNode,
+ '!=': PrimaryCmpNode,
+ '&': IntBinopNode,
+ '^': IntBinopNode,
+ '|': IntBinopNode,
+ '&&': BoolBinopNode,
+ '||': BoolBinopNode,
+}
-cdef public object mul_expr(operand1, operand2):
- return MulNode(pos, operator = "*", operand1 = operand1, operand2 = operand2)
+cdef public object binary_expr(token, operand1, operand2):
+ operator, pos = token
+ cls = binop_node_classes[operator]
+ return cls(pos, operator = operator, operand1 = operand1, operand2 = operand2)
-cdef public object div_expr(operand1, operand2):
- return NumBinopNode(pos, operator = "/", operand1 = operand1, operand2 = operand2)
-cdef public object mod_expr(operand1, operand2):
- return ModNode(pos, operator = "%", operand1 = operand1, operand2 = operand2)
+# expressions -- other
-cdef public object add_expr(operand1, operand2):
- return AddNode(pos, operator = "+", operand1 = operand1, operand2 = operand2)
+cdef public object conditional_expr(question, condition, if_expr, else_expr):
+ _, pos = question
+ return ConditionalNode(pos, condition = condition, if_expr = if_expr, else_expr = else_expr)
-cdef public object sub_expr(operand1, operand2):
- return SubNode(pos, operator = "-", operand1 = operand1, operand2 = operand2)
+cdef public object assignment_expr(token, lhs, rhs):
+ operator, pos = token
+ return CAssignmentNode(pos, operator = operator, lhs = lhs, rhs = rhs)
-cdef public object shift_left_expr(operand1, operand2):
- return IntBinopNode(pos, operator = "<<", operand1 = operand1, operand2 = operand2)
+cdef public object comma_expr(token, lhs, rhs):
+ operator, pos = token
+ return CommaNode(pos, lhs = lhs, rhs = rhs)
-cdef public object shift_right_expr(operand1, operand2):
- return IntBinopNode(pos, operator = ">>", operand1 = operand1, operand2 = operand2)
-cdef public object l_expr(operand1, operand2):
- return PrimaryCmpNode(pos, operator = "<", operand1 = operand1, operand2 = operand2)
-
-cdef public object g_expr(operand1, operand2):
- return PrimaryCmpNode(pos, operator = ">", operand1 = operand1, operand2 = operand2)
-
-cdef public object le_expr(operand1, operand2):
- return PrimaryCmpNode(pos, operator = "<=", operand1 = operand1, operand2 = operand2)
-
-cdef public object ge_expr(operand1, operand2):
- return PrimaryCmpNode(pos, operator = ">=", operand1 = operand1, operand2 = operand2)
-
-cdef public object eq_expr(operand1, operand2):
- return PrimaryCmpNode(pos, operator = "==", operand1 = operand1, operand2 = operand2)
-
-cdef public object ne_expr(operand1, operand2):
- return PrimaryCmpNode(pos, operator = "!=", operand1 = operand1, operand2 = operand2)
-
-cdef public object and_expr(operand1, operand2):
- return IntBinopNode(pos, operator = "&", operand1 = operand1, operand2 = operand2)
-
-cdef public object xor_expr(operand1, operand2):
- return IntBinopNode(pos, operator = "^", operand1 = operand1, operand2 = operand2)
-
-cdef public object or_expr(operand1, operand2):
- return IntBinopNode(pos, operator = "|", operand1 = operand1, operand2 = operand2)
-
-cdef public object logical_and_expr(operand1, operand2):
- return BoolBinopNode(pos, operator = "&&", operand1 = operand1, operand2 = operand2)
-
-cdef public object logical_or_expr(operand1, operand2):
- return BoolBinopNode(pos, operator = "||", operand1 = operand1, operand2 = operand2)
-
-cdef public object assignment_expr(operator, lhs, rhs):
- # NYI
- return SingleAssignmentNode(pos, lhs = lhs, rhs = rhs)
-
-
-# expressions -- unary operators
-
-from Spike.Compiler.ExprNodes import \
- AmpersandNode, \
- IndirectionNode, \
- UnaryPlusNode, \
- UnaryMinusNode, \
- TildeNode, \
- NotNode, \
- PrefixIncNode, \
- PrefixDecNode
-
-cdef public object unary_address_of(): return AmpersandNode, '&'
-cdef public object unary_indirection(): return IndirectionNode, '*'
-cdef public object unary_plus(): return UnaryPlusNode, '+'
-cdef public object unary_minus(): return UnaryMinusNode, '-'
-cdef public object unary_bitwise_negation(): return TildeNode, '~'
-cdef public object unary_not(): return NotNode, '!'
-cdef public object unary_prefix_inc(): return PrefixIncNode, '++'
-cdef public object unary_prefix_dec(): return PrefixDecNode, '--'
-
-
# declarations
from Spike.Compiler.Nodes import \
- CVarDefNode
+ CVarDefNode, \
+ DeclSpecs
cdef public object declaration(object declaration_specifiers, object init_declarator_list):
- # NYI: do some error checking on 'declaration_specifiers'.
- kwds = dict(
- name = 'int', module_path = [],
- is_basic_c_type = 1, signed = 1,
- longness = 0, is_self_arg = 0
- )
- kwds.update(declaration_specifiers)
- base_type = CSimpleBaseTypeNode(pos, **kwds)
- return CVarDefNode(pos, visibility = 'private', base_type = base_type, declarators = init_declarator_list)
+ return declaration_specifiers.declaration(init_declarator_list)
cdef public object declaration_specifiers(object specifier, object declaration_specifiers):
- declaration_specifiers.update(specifier)
+ if declaration_specifiers is None:
+ declaration_specifiers = DeclSpecs()
+ declaration_specifiers.add(specifier)
return declaration_specifiers
cdef public object init_declarator_list(object init_declarator_list, object init_declarator):
@@ -228,20 +223,6 @@
return init_declarator_list
-# declarations -- type specifiers
-
-cdef public object char_type(): return dict(name = 'char')
-cdef public object int_type(): return dict(name = 'int')
-cdef public object float_type(): return dict(name = 'float')
-cdef public object double_type(): return dict(name = 'double')
-cdef public object void_type(): return dict(name = 'void')
-cdef public object obj_type(): return dict(name = 'obj')
-
-cdef public object long_type(): return dict(longness = 1)
-cdef public object signed_type(): return dict(signed = 1)
-cdef public object unsigned_type(): return dict(signed = 0)
-
-
# declarators
from Spike.Compiler.Nodes import \
@@ -253,19 +234,20 @@
cdef public object pointer_declarator(object pointer, object declarator):
last = pointer
- while pointer.base is not None:
- last = pointer.base
+ while last.base is not None:
+ last = last.base
last.base = declarator
return pointer
-cdef public object name_declarator(object name):
+cdef public object name_declarator(object token):
+ name, pos = token
return CNameDeclaratorNode(pos, name = name, cname = None)
cdef public object array_declarator(object base, object dimension):
- return CArrayDeclaratorNode(pos, base = base, dimension = dimension)
+ return CArrayDeclaratorNode(base.pos, base = base, dimension = dimension)
cdef public object function_declarator(object declarator, object parameter_list):
- return CFuncDeclaratorNode(pos,
+ return CFuncDeclaratorNode(declarator.pos,
base = declarator,
args = parameter_list,
has_varargs = 0, #ellipsis,
@@ -273,26 +255,25 @@
exception_check = 0,
)
-cdef public object pointer(object base):
- return CPtrDeclaratorNode(pos, base)
+cdef public object pointer(object asterisk, object type_specifier_list, object base):
+ _, pos = asterisk
+ if type_specifier_list is not None:
+ # NYI: currently discarded
+ modifiers = type_specifier_list.analyse_type_modifiers()
+ return CPtrDeclaratorNode(pos, base = base)
cdef public object type_specifier_list(object type_specifier_list, object type_specifier):
if type_specifier_list is None:
- type_specifier_list = CSimpleBaseTypeNode(
- pos,
- name = 'int', module_path = [],
- is_basic_c_type = 1, signed = 1,
- longness = 0, is_self_arg = 0
- )
- # NYI: do some error checking.
- type_specifier_list.__dict__.update(type_specifier)
+ type_specifier_list = DeclSpecs()
+ type_specifier_list.add(type_specifier)
return type_specifier_list
cdef public object parameter_list(object parameter_list, object parameter_declaration):
if parameter_list is None:
parameter_list = []
- base_type, declarator = parameter_declaration
- node = CArgDeclNode(pos,
+ type_specifier_list, declarator = parameter_declaration
+ base_type = type_specifier_list.analyse_type()
+ node = CArgDeclNode(declarator.pos,
base_type = base_type,
declarator = declarator,
not_none = 0,
@@ -300,17 +281,13 @@
parameter_list.append(node)
return parameter_list
-
-# abstract declarators
-
cdef public object empty_declarator():
- return CNameDeclaratorNode(pos, name = "", cname = None)
+ return CNameDeclaratorNode(pos = None, name = "", cname = None)
# statements
from Spike.Compiler.Nodes import \
- StatListNode, \
PassStatNode, \
ExprStatNode, \
IfClauseNode, \
@@ -318,7 +295,8 @@
WhileStatNode, \
ReturnStatNode
-cdef public object compound_statement(object declaration_list, object statement_list):
+cdef public object compound_statement(object lcurly, object declaration_list, object statement_list):
+ _, pos = lcurly
stats = []
if declaration_list is not None:
stats.extend(declaration_list.stats)
@@ -329,61 +307,79 @@
cdef public object declaration_list(object declaration_list, object declaration):
if declaration_list is None:
- declaration_list = StatListNode(pos, stats = [])
- declaration_list.stats.append(declaration)
+ declaration_list = StatListNode(declaration.pos, stats = [])
+ declaration_list.stats.extend(declaration.stats)
return declaration_list
cdef public object statement_list(object statement_list, object statement):
if statement_list is None:
- statement_list = StatListNode(pos, stats = [])
+ statement_list = StatListNode(statement.pos, stats = [])
statement_list.stats.append(statement)
return statement_list
-cdef public object pass_statement():
+cdef public object pass_statement(object semicolon):
+ _, pos = semicolon
return PassStatNode(pos)
cdef public object expression_statement(object expr):
from Spike.Compiler.Nodes import StatNode
- if isinstance(expr, StatNode):
- # NYI -- AssignmentNodes currently go though here
- return expr
- return ExprStatNode(pos, expr = expr)
+ return ExprStatNode(expr.pos, expr = expr)
-cdef public object if_statement(object condition, object if_clause, object else_clause):
+cdef public object if_statement(object keyword, object condition, object if_clause, object else_clause):
+ _, pos = keyword
if_clauses = [IfClauseNode(pos, condition = condition, body = if_clause)]
return IfStatNode(pos, if_clauses = if_clauses, else_clause = else_clause)
-cdef public object while_statement(object expr, object statement):
+cdef public object while_statement(object keyword, object expr, object statement):
+ _, pos = keyword
return WhileStatNode(pos, condition = expr, body = statement, else_clause = None)
-cdef public object return_statement(object value):
+cdef public object return_statement(object keyword, object value):
+ _, pos = keyword
return ReturnStatNode(pos, value = value)
# external definitions
cdef public void external_definition(object definition):
- theDefList.append(definition)
+ global theDefList
+ theDefList.stats.extend(definition.stats)
cdef public object function_definition(object declaration_specifiers,
object declarator,
object function_body):
- # NYI: do some error checking on 'declaration_specifiers'.
- kwds = dict(
- name = 'int', module_path = [],
- is_basic_c_type = 1, signed = 1,
- longness = 0, is_self_arg = 0
- )
- kwds.update(declaration_specifiers)
- base_type = CSimpleBaseTypeNode(pos, **kwds)
- func = SpikeFuncDefNode(pos,
- visibility = 'public',
- base_type = base_type,
- declarator = declarator,
- body = function_body)
- return func
+ return declaration_specifiers.function_definition(declarator, function_body)
+# scope
+
+scopeStack = []
+
+cdef public void push_scope():
+ global scopeStack
+ newScope = dict()
+ scopeStack.insert(0, newScope)
+
+cdef public void pop_scope():
+ global scopeStack
+ scopeStack.pop(0)
+
+cdef public object name_token(char *text, int line, int column, int *is_type_name):
+ global scopeStack
+ name = str(text)
+ is_type_name[0] = 0
+ for scope in scopeStack:
+ if scope.has_key(name):
+ is_type_name[0] = 1
+ global currentFilename
+ return (name, (currentFilename, line, column))
+
+def declare_type_name(name):
+ global scopeStack
+ scope = scopeStack[0]
+ scope[name] = True
+
+
# utils
cdef public object empty_list():
@@ -392,11 +388,16 @@
cdef public object pair(object a, object b):
return a, b
-cdef public object name(char *text):
- return str(text)
+cdef public object token(char *text, int line, int column):
+ global currentFilename
+ return (str(text), (currentFilename, line, column))
-cdef public object yystr(char *text):
- return str(text)
+cdef public void yyerror(char *s):
+ cdef extern int yylineno
+ cdef extern int column
+ from Spike.Compiler.Errors import error
+ pos = (currentFilename, yylineno, column)
+ error(pos, s)
# end of file
Modified: cs/babel/trunk/spike/Spike/Compiler/scan.l
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/scan.l 2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/scan.l 2007-02-25 02:38:54 UTC (rev 6113)
@@ -1,3 +1,5 @@
+%option yylineno
+
D [0-9]
L [a-zA-Z_]
H [a-fA-F0-9]
@@ -14,164 +16,158 @@
#include "gram.h"
#include "parser.h"
+#define TOKEN(t) get_token(); return t
+
void count();
+void comment();
+void get_token();
+int get_name_token();
%}
%%
"/*" { comment(); }
-"auto" { count(); return(AUTO); }
-"break" { count(); return(BREAK); }
-"case" { count(); return(CASE); }
-"char" { count(); return(CHAR); }
-"const" { count(); return(CONST); }
-"continue" { count(); return(CONTINUE); }
-"default" { count(); return(DEFAULT); }
-"do" { count(); return(DO); }
-"double" { count(); return(DOUBLE); }
-"else" { count(); return(ELSE); }
-"enum" { count(); return(ENUM); }
-"extern" { count(); return(EXTERN); }
-"float" { count(); return(FLOAT); }
-"for" { count(); return(FOR); }
-"goto" { count(); return(GOTO); }
-"if" { count(); return(IF); }
-"int" { count(); return(INT); }
-"long" { count(); return(LONG); }
-"obj" { count(); return(OBJ); }
-"register" { count(); return(REGISTER); }
-"return" { count(); return(RETURN); }
-"short" { count(); return(SHORT); }
-"signed" { count(); return(SIGNED); }
-"sizeof" { count(); return(SIZEOF); }
-"static" { count(); return(STATIC); }
-"struct" { count(); return(STRUCT); }
-"switch" { count(); return(SWITCH); }
-"typedef" { count(); return(TYPEDEF); }
-"union" { count(); return(UNION); }
-"unsigned" { count(); return(UNSIGNED); }
-"void" { count(); return(VOID); }
-"volatile" { count(); return(VOLATILE); }
-"while" { count(); return(WHILE); }
+"auto" { TOKEN(AUTO); }
+"break" { TOKEN(BREAK); }
+"case" { TOKEN(CASE); }
+"char" { TOKEN(CHAR); }
+"const" { TOKEN(CONST); }
+"continue" { TOKEN(CONTINUE); }
+"default" { TOKEN(DEFAULT); }
+"do" { TOKEN(DO); }
+"double" { TOKEN(DOUBLE); }
+"else" { TOKEN(ELSE); }
+"enum" { TOKEN(ENUM); }
+"extern" { TOKEN(EXTERN); }
+"float" { TOKEN(FLOAT); }
+"for" { TOKEN(FOR); }
+"goto" { TOKEN(GOTO); }
+"if" { TOKEN(IF); }
+"int" { TOKEN(INT); }
+"long" { TOKEN(LONG); }
+"obj" { TOKEN(OBJ); }
+"register" { TOKEN(REGISTER); }
+"return" { TOKEN(RETURN); }
+"short" { TOKEN(SHORT); }
+"signed" { TOKEN(SIGNED); }
+"sizeof" { TOKEN(SIZEOF); }
+"static" { TOKEN(STATIC); }
+"struct" { TOKEN(STRUCT); }
+"switch" { TOKEN(SWITCH); }
+"typedef" { TOKEN(TYPEDEF); }
+"union" { TOKEN(UNION); }
+"unsigned" { TOKEN(UNSIGNED); }
+"void" { TOKEN(VOID); }
+"volatile" { TOKEN(VOLATILE); }
+"while" { TOKEN(WHILE); }
-{L}({L}|{D})* { count(); return(check_type()); }
+{L}({L}|{D})* { TOKEN(get_name_token()); }
-0[xX]{H}+{IS}? { count(); yylval = yystr(yytext); return(LITERAL_INT); }
-0{D}+{IS}? { count(); yylval = yystr(yytext); return(LITERAL_INT); }
-{D}+{IS}? { count(); yylval = yystr(yytext); return(LITERAL_INT); }
-'(\\.|[^\\'])+' { count(); yylval = yystr(yytext); return(LITERAL_CHAR); }
+0[xX]{H}+{IS}? { TOKEN(LITERAL_INT); }
+0{D}+{IS}? { TOKEN(LITERAL_INT); }
+{D}+{IS}? { TOKEN(LITERAL_INT); }
+'(\\.|[^\\'])+' { TOKEN(LITERAL_CHAR); }
-{D}+{E}{FS}? { count(); yylval = yystr(yytext); return(LITERAL_FLOAT); }
-{D}*"."{D}+({E})?{FS}? { count(); yylval = yystr(yytext); return(LITERAL_FLOAT); }
-{D}+"."{D}*({E})?{FS}? { count(); yylval = yystr(yytext); return(LITERAL_FLOAT); }
+{D}+{E}{FS}? { TOKEN(LITERAL_FLOAT); }
+{D}*"."{D}+({E})?{FS}? { TOKEN(LITERAL_FLOAT); }
+{D}+"."{D}*({E})?{FS}? { TOKEN(LITERAL_FLOAT); }
-\"(\\.|[^\\"])*\" { count(); yylval = yystr(yytext); return(LITERAL_STRING); }
+\"(\\.|[^\\"])*\" { TOKEN(LITERAL_STRING); }
-">>=" { count(); return(RIGHT_ASSIGN); }
-"<<=" { count(); return(LEFT_ASSIGN); }
-"+=" { count(); return(ADD_ASSIGN); }
-"-=" { count(); return(SUB_ASSIGN); }
-"*=" { count(); return(MUL_ASSIGN); }
-"/=" { count(); return(DIV_ASSIGN); }
-"%=" { count(); return(MOD_ASSIGN); }
-"&=" { count(); return(AND_ASSIGN); }
-"^=" { count(); return(XOR_ASSIGN); }
-"|=" { count(); return(OR_ASSIGN); }
-">>" { count(); return(RIGHT_OP); }
-"<<" { count(); return(LEFT_OP); }
-"++" { count(); return(INC_OP); }
-"--" { count(); return(DEC_OP); }
-"->" { count(); return(PTR_OP); }
-"&&" { count(); return(AND_OP); }
-"||" { count(); return(OR_OP); }
-"<=" { count(); return(LE_OP); }
-">=" { count(); return(GE_OP); }
-"==" { count(); return(EQ_OP); }
-"!=" { count(); return(NE_OP); }
-";" { count(); return(';'); }
-"{" { count(); return('{'); }
-"}" { count(); return('}'); }
-"," { count(); return(','); }
-":" { count(); return(':'); }
-"=" { count(); return('='); }
-"(" { count(); return('('); }
-")" { count(); return(')'); }
-"[" { count(); return('['); }
-"]" { count(); return(']'); }
-"." { count(); return('.'); }
-"&" { count(); return('&'); }
-"!" { count(); return('!'); }
-"~" { count(); return('~'); }
-"-" { count(); return('-'); }
-"+" { count(); return('+'); }
-"*" { count(); return('*'); }
-"/" { count(); return('/'); }
-"%" { count(); return('%'); }
-"<" { count(); return('<'); }
-">" { count(); return('>'); }
-"^" { count(); return('^'); }
-"|" { count(); return('|'); }
-"?" { count(); return('?'); }
+">>=" { TOKEN(RIGHT_ASSIGN); }
+"<<=" { TOKEN(LEFT_ASSIGN); }
+"+=" { TOKEN(ADD_ASSIGN); }
+"-=" { TOKEN(SUB_ASSIGN); }
+"*=" { TOKEN(MUL_ASSIGN); }
+"/=" { TOKEN(DIV_ASSIGN); }
+"%=" { TOKEN(MOD_ASSIGN); }
+"&=" { TOKEN(AND_ASSIGN); }
+"^=" { TOKEN(XOR_ASSIGN); }
+"|=" { TOKEN(OR_ASSIGN); }
+">>" { TOKEN(RIGHT_OP); }
+"<<" { TOKEN(LEFT_OP); }
+"++" { TOKEN(INC_OP); }
+"--" { TOKEN(DEC_OP); }
+"->" { TOKEN(PTR_OP); }
+"&&" { TOKEN(AND_OP); }
+"||" { TOKEN(OR_OP); }
+"<=" { TOKEN(LE_OP); }
+">=" { TOKEN(GE_OP); }
+"==" { TOKEN(EQ_OP); }
+"!=" { TOKEN(NE_OP); }
+";" { TOKEN(';'); }
+"{" { TOKEN('{'); }
+"}" { TOKEN('}'); }
+"," { TOKEN(','); }
+":" { TOKEN(':'); }
+"=" { TOKEN('='); }
+"(" { TOKEN('('); }
+")" { TOKEN(')'); }
+"[" { TOKEN('['); }
+"]" { TOKEN(']'); }
+"." { TOKEN('.'); }
+"&" { TOKEN('&'); }
+"!" { TOKEN('!'); }
+"~" { TOKEN('~'); }
+"-" { TOKEN('-'); }
+"+" { TOKEN('+'); }
+"*" { TOKEN('*'); }
+"/" { TOKEN('/'); }
+"%" { TOKEN('%'); }
+"<" { TOKEN('<'); }
+">" { TOKEN('>'); }
+"^" { TOKEN('^'); }
+"|" { TOKEN('|'); }
+"?" { TOKEN('?'); }
[ \t\v\n\f] { count(); }
. { /* ignore bad characters */ }
%%
-yywrap()
+int yywrap()
{
- return(1);
+ return 1;
}
-comment()
+void comment()
{
- char c, c1;
-
-loop:
- while ((c = input()) != '*' && c != 0)
- putchar(c);
-
- if ((c1 = input()) != '/' && c != 0)
- {
- /*unput(c1);*/
- goto loop;
- }
-
- if (c != 0)
- putchar(c1);
+ char c, c1;
+
+ c = input();
+ do {
+ while (c != '*') {
+ if (!c) return;
+ c = input();
+ }
+ c = input();
+ } while (c != '/');
}
int column = 0;
void count()
{
- int i;
+ int i;
- for (i = 0; yytext[i] != '\0'; i++)
- if (yytext[i] == '\n')
- column = 0;
- else if (yytext[i] == '\t')
- column += 8 - (column % 8);
- else
- column++;
-
- ECHO;
+ for (i = 0; yytext[i] != '\0'; i++)
+ if (yytext[i] == '\n')
+ column = 0;
+ else if (yytext[i] == '\t')
+ column += 4 - (column % 4);
+ else
+ column++;
}
-int check_type()
+void get_token()
{
-/*
-* pseudo code --- this is what it should check
-*
-* if (yytext == type_name)
-* return(TYPE_NAME);
-*
-* return(IDENTIFIER);
-*/
+ count();
+ yylval = token(yytext, yylineno, column);
+}
-/*
-* it actually will only return IDENTIFIER
-*/
- yylval = name(yytext);
- return(IDENTIFIER);
+int get_name_token()
+{
+ int is_type_name;
+ yylval = name_token(yytext, yylineno, column, &is_type_name);
+ return is_type_name ? TYPE_NAME : IDENTIFIER;
}
More information about the cig-commits
mailing list