Browse Source

Rust codegen: progress with test generation

Joeri Exelmans 4 years ago
parent
commit
9c7164bb0d

+ 6 - 2
src/sccd/statechart/cmd/gen_rust.py

@@ -8,6 +8,8 @@ from sccd.test.parser.xml import *
 from sccd.statechart.codegen.rust import compile_statechart
 from sccd.test.codegen.rust import compile_test
 
+from sccd.util.indenting_writer import *
+
 # Note: Rust code is written to stdout and should be compiled to a library
 
 # Test syntax correctness as follows:
@@ -35,10 +37,12 @@ if __name__ == "__main__":
 
     statechart_or_test = parse_f(src, rules)
 
+    w = IndentingWriter()
+
     if isinstance(statechart_or_test, Statechart):
         sys.stderr.write("Loaded statechart.\n")
-        compile_statechart(statechart_or_test, globals)
+        compile_statechart(statechart_or_test, globals, w)
 
     elif isinstance(statechart_or_test, list) and reduce(lambda x,y: x and y, (isinstance(test, TestVariant) for test in statechart_or_test)):
         sys.stderr.write("Loaded test.\n")
-        compile_test(statechart_or_test)
+        compile_test(statechart_or_test, w)

+ 20 - 20
src/sccd/statechart/cmd/render.py

@@ -96,40 +96,40 @@ if __name__ == '__main__':
 
         def write_state(s, hide=False):
           if not hide:
-            w.write(name_to_name(s.opt.full_name))
-            w.extendWrite(' [label="')
-            w.extendWrite(name_to_label(s))
-            w.extendWrite('"')
+            w.writeln(name_to_name(s.opt.full_name))
+            w.write(' [label="')
+            w.write(name_to_label(s))
+            w.write('"')
             if isinstance(s, ParallelState):
-              w.extendWrite(' type=parallel')
+              w.write(' type=parallel')
             elif isinstance(s, ShallowHistoryState):
-              w.extendWrite(' type=history')
+              w.write(' type=history')
             elif isinstance(s, DeepHistoryState):
-              w.extendWrite(' type=deephistory')
+              w.write(' type=deephistory')
             else:
-              w.extendWrite(' type=regular')
-            w.extendWrite(']')
+              w.write(' type=regular')
+            w.write(']')
           if s.enter or s.exit:
-            w.extendWrite(' :')
+            w.write(' :')
             for a in s.enter:
-              w.write("enter "+a.render())
+              w.writeln("enter "+a.render())
             for a in s.exit:
-              w.write("exit "+a.render())
-            w.write()
+              w.writeln("exit "+a.render())
+            w.writeln()
           if s.children:
             if not hide:
-              w.extendWrite(' {')
+              w.write(' {')
               w.indent()
             if s.default_state:
-              w.write(name_to_name(s.opt.full_name)+'_initial [type=initial],')
+              w.writeln(name_to_name(s.opt.full_name)+'_initial [type=initial],')
               transitions.append(PseudoTransition(source=PseudoState(s.opt.full_name+'/initial'), target=s.default_state))
             s.children.reverse() # this appears to put orthogonal components in the right order :)
             for i, c in enumerate(s.children):
               write_state(c)
-              w.extendWrite(',' if i < len(s.children)-1 else ';')
+              w.write(',' if i < len(s.children)-1 else ';')
             if not hide:
               w.dedent()
-              w.write('}')
+              w.writeln('}')
           transitions.extend(s.transitions)
 
         write_state(root, hide=True)
@@ -144,10 +144,10 @@ if __name__ == '__main__':
           if t.actions:
             label += ' '.join(a.render() for a in t.actions)
 
-          w.write(name_to_name(t.source.opt.full_name) + ' -> ' + name_to_name(t.target.opt.full_name))
+          w.writeln(name_to_name(t.source.opt.full_name) + ' -> ' + name_to_name(t.target.opt.full_name))
           if label:
-            w.extendWrite(': '+label)
-          w.extendWrite(';')
+            w.write(': '+label)
+          w.write(';')
 
         f.close()
         if args.keep_smcat:

+ 127 - 117
src/sccd/statechart/codegen/rust.py

@@ -3,6 +3,7 @@ from sccd.statechart.static.tree import *
 from sccd.util.visit_tree import *
 from sccd.statechart.static.statechart import *
 from sccd.statechart.static.globals import *
+from sccd.util.indenting_writer import *
 
 # Conversion functions from abstract syntax elements to identifiers in Rust
 
@@ -43,7 +44,7 @@ def ident_arena_label(state: State) -> str:
         return "arena" + snake_case(state)
 
 
-def compile_statechart(sc: Statechart, globals: Globals):
+def compile_statechart(sc: Statechart, globals: Globals, w: IndentingWriter):
 
     tree = sc.tree
 
@@ -63,25 +64,25 @@ def compile_statechart(sc: Statechart, globals: Globals):
             return None # we got no time for pseudo-states!
 
         def as_struct():
-            print("#[allow(non_camel_case_types)]")
-            print("struct %s {" % ident_type(state))
+            w.writeln("#[allow(non_camel_case_types)]")
+            w.writeln("struct %s {" % ident_type(state))
             for child in children:
-                print("  %s: %s," % (ident_field(child), ident_type(child)))
-            print("}")
+                w.writeln("  %s: %s," % (ident_field(child), ident_type(child)))
+            w.writeln("}")
 
         def as_enum():
-            print("#[allow(non_camel_case_types)]")
-            print("enum %s {" % ident_type(state))
+            w.writeln("#[allow(non_camel_case_types)]")
+            w.writeln("enum %s {" % ident_type(state))
             for child in children:
-                print("  %s(%s)," % (ident_enum_variant(child), ident_type(child)))
-            print("}")
+                w.writeln("  %s(%s)," % (ident_enum_variant(child), ident_type(child)))
+            w.writeln("}")
 
         if isinstance(state, ParallelState):
-            print("// And-state")
+            w.writeln("// And-state")
             as_struct()
         elif isinstance(state, State):
             if len(state.children) > 0:
-                print("// Or-state")
+                w.writeln("// Or-state")
                 as_enum() # Or-state
             else:
                 # Basic state: write as empty struct
@@ -91,54 +92,56 @@ def compile_statechart(sc: Statechart, globals: Globals):
                 #
                 # An empty enum is also a valid type in Rust, but no instances
                 # of it can be created. Also called an "uninhabited type".
-                print("// Basic state")
+                w.writeln("// Basic state")
                 as_struct()
 
             # The above if-else construction hints at the fact that we would have
             # better used empty And-states to model basic states, instead of empty Or-states...
 
-        print()
+        w.writeln()
         return state
 
 
     # Write "enter/exit state" functions
 
     # This fragment should be moved to a library:
-    print("pub trait State {")
-    print("  fn enter_actions();")
-    print("  fn exit_actions();")
-    print("  fn enter_default();")
-    print("}")
-    print()
+    w.writeln("pub trait State {")
+    w.writeln("  fn enter_actions();")
+    w.writeln("  fn exit_actions();")
+    w.writeln("  fn enter_default();")
+    w.writeln("}")
+    w.writeln()
 
     def write_enter_exit(state: State, children: List[State]):
         if isinstance(state, HistoryState):
             return None # we got no time for pseudo-states!
 
-        print("impl State for %s {" % ident_type(state))
+        w.writeln("impl State for %s {" % ident_type(state))
 
-        print("  fn enter_actions() {")
-        print("    // TODO: execute enter actions here")
-        print("    println!(\"enter %s\");" % state.opt.full_name);
-        print("  }")
+        w.writeln("  fn enter_actions() {")
+        w.writeln("    println!(\"enter %s\");" % state.opt.full_name);
+        for a in state.enter:
+            w.writeln("    println!(\"%s\");" % a.render())
+        w.writeln("  }")
 
-        print("  fn exit_actions() {")
-        print("    // TODO: execute exit actions here")
-        print("    println!(\"exit %s\");" % state.opt.full_name);
-        print("  }")
+        w.writeln("  fn exit_actions() {")
+        w.writeln("    println!(\"exit %s\");" % state.opt.full_name);
+        for a in state.exit:
+            w.writeln("    println!(\"%s\");" % a.render())
+        w.writeln("  }")
 
-        print("  fn enter_default() {")
-        print("    %s::enter_actions();" % ident_type(state))
+        w.writeln("  fn enter_default() {")
+        w.writeln("    %s::enter_actions();" % ident_type(state))
         if isinstance(state, ParallelState):
             for child in children:
-                print("    %s::enter_default();" % ident_type(child))
+                w.writeln("    %s::enter_default();" % ident_type(child))
         else:
             if state.default_state is not None:
-                print("    %s::enter_default();" % ident_type(state.default_state))
-        print("  }")
+                w.writeln("    %s::enter_default();" % ident_type(state.default_state))
+        w.writeln("  }")
 
-        print("}")
-        print()
+        w.writeln("}")
+        w.writeln()
         return state
 
 
@@ -151,25 +154,25 @@ def compile_statechart(sc: Statechart, globals: Globals):
         # We use Rust's Default-trait to record default states,
         # this way, constructing a state instance without parameters will initialize it as the default state.
 
-        print("impl Default for %s {" % ident_type(state))
-        print("  fn default() -> Self {")
+        w.writeln("impl Default for %s {" % ident_type(state))
+        w.writeln("  fn default() -> Self {")
 
         if isinstance(state, ParallelState):
-            print("    return Self {")
+            w.writeln("    return Self {")
             for child in children:
-                print("      %s: Default::default()," % (ident_field(child)))
-            print("    };")
+                w.writeln("      %s: Default::default()," % (ident_field(child)))
+            w.writeln("    };")
         elif isinstance(state, State):
             if state.default_state is not None:
                 # Or-state
-                print("    return Self::%s(Default::default());" % (ident_enum_variant(state.default_state)))
+                w.writeln("    return Self::%s(Default::default());" % (ident_enum_variant(state.default_state)))
             else:
                 # Basic state
-                print("    return Self{};")
+                w.writeln("    return Self{};")
 
-        print("  }")
-        print("}")
-        print()
+        w.writeln("  }")
+        w.writeln("}")
+        w.writeln()
         return state
 
     visit_tree(tree.root, lambda s: s.children,
@@ -181,37 +184,38 @@ def compile_statechart(sc: Statechart, globals: Globals):
 
     # Write event type
 
-    print("#[allow(non_camel_case_types)]")
-    print("enum Event {")
+    w.writeln("#[allow(non_camel_case_types)]")
+    w.writeln("enum Event {")
     for event_name in (globals.events.names[i] for i in bm_items(sc.internal_events)):
-        print("  %s," % event_name)
-    print("}")
-    print()
+        w.writeln("  %s," % event_name)
+    w.writeln("}")
+    w.writeln()
 
     # Write statechart type
-    print("pub struct Statechart {")
-    print("  current_state: %s," % ident_type(tree.root))
-    print("  // TODO: history values")
-    print("  // TODO: timers")
-    print("}")
-    print()
-
-    class IndentingWriter:
-        def __init__(self, spaces = 0):
-            self.spaces = spaces
-        def indent(self):
-            self.spaces += 2
-        def dedent(self):
-            self.spaces -= 2
-        def print(self, str):
-            print(' '*self.spaces + str)
-
-    print("impl Statechart {")
-    print("  fn fair_step(&mut self, event: Option<Event>) {")
-    print("    println!(\"fair step\");")
-    print("    let %s = &mut self.current_state;" % ident_var(tree.root))
-
-    w = IndentingWriter(4)
+    w.writeln("pub struct Statechart {")
+    w.writeln("  current_state: %s," % ident_type(tree.root))
+    w.writeln("  // TODO: history values")
+    w.writeln("  // TODO: timers")
+    w.writeln("}")
+    w.writeln()
+
+    w.writeln("impl Default for Statechart {")
+    w.writeln("  fn default() -> Self {")
+    w.writeln("    return Self{")
+    w.writeln("      current_state: Default::default(),")
+    # w.writeln("      history: Default::default(),")
+    # w.writeln("      timers: Default::default(),")
+    w.writeln("    };")
+    w.writeln("  }")
+    w.writeln("}")
+
+    w.writeln("impl Statechart {")
+    w.writeln("  fn fair_step(&mut self, event: Option<Event>) {")
+    w.writeln("    println!(\"fair step\");")
+    w.writeln("    let %s = &mut self.current_state;" % ident_var(tree.root))
+
+    w.indent()
+    w.indent()
 
     def write_transitions(state: State):
         if isinstance(state, HistoryState):
@@ -229,7 +233,7 @@ def compile_statechart(sc: Statechart, globals: Globals):
         # (2) The descendants of S, if S is the transition target
         def write_exit(exit_path: List[State]):
             if len(exit_path) == 0:
-                w.print("%s.exit();" % ident_var(s))
+                w.writeln("%s.exit();" % ident_var(s))
             else:
                 s = exit_path[0]
                 if isinstance(s, HistoryState):
@@ -239,12 +243,12 @@ def compile_statechart(sc: Statechart, globals: Globals):
                         if exit_path[1] is c:
                             write_exit(exit_path[1:]) # continue recursively
                         else:
-                            w.print("%s.exit();" % ident_var(c))
+                            w.writeln("%s.exit();" % ident_var(c))
                 elif isinstance(s, State):
                     if s.default_state is not None:
                         # Or-state
                         write_exit(exit_path[1:]) # continue recursively with the next child on the exit path
-                w.print("%s::exit_actions();" % ident_type(s))
+                w.writeln("%s::exit_actions();" % ident_type(s))
 
         def write_new_configuration(enter_path: List[State]):
             if len(enter_path) > 0:
@@ -252,7 +256,7 @@ def compile_statechart(sc: Statechart, globals: Globals):
                 if len(enter_path) == 1:
                     # Construct target state.
                     # Whatever the type of parent (And/Or/Basic), just construct the default value:
-                    w.print("let new_%s: %s = Default::default();" % (ident_var(s), ident_type(s)))
+                    w.writeln("let new_%s: %s = Default::default();" % (ident_var(s), ident_type(s)))
                 else:
                     if isinstance(s, ParallelState):
                         for c in s.children:
@@ -260,15 +264,15 @@ def compile_statechart(sc: Statechart, globals: Globals):
                                 write_new_configuration(enter_path[1:]) # recurse
                             else:
                                 # Other children's default states are constructed
-                                w.print("let new_%s: %s = Default::default();" % (ident_var(c), ident_type(c)))
+                                w.writeln("let new_%s: %s = Default::default();" % (ident_var(c), ident_type(c)))
                         # Construct struct
-                        w.print("let new_%s = %s{%s:%s, ..Default::default()};" % (ident_var(s), ident_type(s), ident_field(enter_path[1]), ident_var(enter_path[1])))
+                        w.writeln("let new_%s = %s{%s:%s, ..Default::default()};" % (ident_var(s), ident_type(s), ident_field(enter_path[1]), ident_var(enter_path[1])))
 
                     elif isinstance(s, State):
                         if len(s.children) > 0:
                             # Or-state
                             write_new_configuration(enter_path[1:]) # recurse
-                            w.print("let new_%s = %s::%s(new_%s);" % (ident_var(s), ident_type(s), ident_enum_variant(enter_path[1]), ident_var(enter_path[1])))
+                            w.writeln("let new_%s = %s::%s(new_%s);" % (ident_var(s), ident_type(s), ident_enum_variant(enter_path[1]), ident_var(enter_path[1])))
                         else:
                             # The following should never occur
                             # The parser should have rejected the model before we even get here
@@ -280,19 +284,19 @@ def compile_statechart(sc: Statechart, globals: Globals):
                 s = enter_path[0]
                 if len(enter_path) == 1:
                     # Target state.
-                    w.print("%s::enter_default();" % ident_type(s))
+                    w.writeln("%s::enter_default();" % ident_type(s))
                 else:
                     if isinstance(s, ParallelState):
                         for c in s.children:
                             if enter_path[1] is c:
-                                w.print("%s::enter_actions();" % ident_type(c))
+                                w.writeln("%s::enter_actions();" % ident_type(c))
                                 write_enter(enter_path[1:]) # continue recursively
                             else:
-                                w.print("%s::enter_default();" % ident_type(c))
+                                w.writeln("%s::enter_default();" % ident_type(c))
                     elif isinstance(s, State):
                         if len(s.children) > 0:
                             # Or-state
-                            w.print("%s::enter_actions();" & ident_type(s))
+                            w.writeln("%s::enter_actions();" & ident_type(s))
                             write_enter(enter_path[1:]) # continue recursively with the next child on the enter path
                         else:
                             # The following should never occur
@@ -301,12 +305,12 @@ def compile_statechart(sc: Statechart, globals: Globals):
 
         def parent():
             for t in state.transitions:
-                w.print("// Outgoing transition")
+                w.writeln("// Outgoing transition")
 
                 if t.trigger is not EMPTY_TRIGGER:
                     if len(t.trigger.enabling) > 1:
                         raise Exception("Multi-event triggers currently unsupported")
-                    w.print("if let Some(Event::%s) = event {" % t.trigger.enabling[0].name)
+                    w.writeln("if let Some(Event::%s) = event {" % t.trigger.enabling[0].name)
                     w.indent()
 
                 # 1. Execute transition's actions
@@ -319,55 +323,59 @@ def compile_statechart(sc: Statechart, globals: Globals):
                 enter_path_bm = t.opt.arena.opt.descendants & (t.target.opt.state_id_bitmap | t.target.opt.ancestors) # bitmap
                 enter_path = list(tree.bitmap_to_states(enter_path_bm)) # list of states
 
-                w.print("// Exit actions")
+                w.writeln("println!(\"fire %s\");" % str(t))
+
+                w.writeln("// Exit actions")
                 write_exit(exit_path)
 
-                w.print("// Transition's actions")
-                w.print("println!(\"%s\");" % str(t))
+                if len(t.actions) > 0:
+                    w.writeln("// Transition's actions")
+                    for a in t.actions:
+                        w.writeln("println!(%s);" % a.render())
 
-                w.print("// Enter actions")
+                w.writeln("// Enter actions")
                 write_enter(enter_path)
 
                 # 2. Update state
 
                 # A state configuration is just a value
-                w.print("// Build new state configuration")
+                w.writeln("// Build new state configuration")
                 write_new_configuration([t.opt.arena] + enter_path)
 
-                w.print("// Update arena configuration")
-                w.print("*%s = new_%s;" % (ident_var(t.opt.arena), ident_var(t.opt.arena)))
+                w.writeln("// Update arena configuration")
+                w.writeln("*%s = new_%s;" % (ident_var(t.opt.arena), ident_var(t.opt.arena)))
 
                 # This arena is done:
-                w.print("break '%s;" % (ident_arena_label(t.opt.arena)))
+                w.writeln("break '%s;" % (ident_arena_label(t.opt.arena)))
 
                 if t.trigger is not EMPTY_TRIGGER:
                     w.dedent()
-                    w.print("}")
+                    w.writeln("}")
 
         def child():
             if isinstance(state, ParallelState):
                 for child in state.children:
-                    w.print("// Orthogonal region")
-                    w.print("let %s = &mut %s.%s;" % (ident_var(child), ident_var(state), ident_field(child)))
+                    w.writeln("// Orthogonal region")
+                    w.writeln("let %s = &mut %s.%s;" % (ident_var(child), ident_var(state), ident_field(child)))
                     write_transitions(child)
             elif isinstance(state, State):
                 if state.default_state is not None:
-                    w.print("'%s: loop {" % ident_arena_label(state))
+                    w.writeln("'%s: loop {" % ident_arena_label(state))
                     w.indent()
-                    w.print("match %s {" % ident_var(state))
+                    w.writeln("match %s {" % ident_var(state))
                     for child in state.children:
                         w.indent()
-                        # w.print("%s::%s(%s) => {" % (ident_type(state), ident_enum_variant(child), ident_var(child)))
-                        w.print("%s::%s(_) => {" % (ident_type(state), ident_enum_variant(child)))
+                        # w.writeln("%s::%s(%s) => {" % (ident_type(state), ident_enum_variant(child), ident_var(child)))
+                        w.writeln("%s::%s(_) => {" % (ident_type(state), ident_enum_variant(child)))
                         w.indent()
                         write_transitions(child)
                         w.dedent()
-                        w.print("},")
+                        w.writeln("},")
                         w.dedent()
-                    w.print("};")
-                    w.print("break;")
+                    w.writeln("};")
+                    w.writeln("break;")
                     w.dedent()
-                    w.print("}")
+                    w.writeln("}")
 
         # TODO: This is where parent/child-first semantic variability should be implemented
         #       For now, it's always "parent first"
@@ -376,17 +384,19 @@ def compile_statechart(sc: Statechart, globals: Globals):
 
     write_transitions(tree.root)
 
-    print("  }")
-    print("}")
-    print()
+    w.dedent()
+    w.dedent()
+
+    w.writeln("  }")
+    w.writeln("}")
+    w.writeln()
 
 
-    # See if it works
-    print("fn main() {")
-    print("  let mut sc = Statechart{current_state: Default::default()};")
-    print("  Root::enter_default();")
-    print("  sc.fair_step(None);")
-    print("  sc.fair_step(None);")
-    # print("  sc.current_state.exit();")
-    print("}")
-    print()
+    # # See if it works
+    # w.writeln("fn main() {")
+    # w.writeln("  let mut sc: Statechart = Default::default();")
+    # w.writeln("  Root::enter_default();")
+    # w.writeln("  sc.fair_step(None);")
+    # w.writeln("  sc.fair_step(None);")
+    # w.writeln("}")
+    # w.writeln()

+ 22 - 3
src/sccd/test/codegen/rust.py

@@ -1,10 +1,29 @@
 from sccd.test.static.syntax import *
 from sccd.statechart.codegen.rust import compile_statechart
+from sccd.util.indenting_writer import *
 
-def compile_test(variants: List[TestVariant]):
+def compile_test(variants: List[TestVariant], w: IndentingWriter):
     if len(variants) > 0:
         cd = variants[0].cd
-        compile_statechart(cd.get_default_class(), cd.globals)
+        compile_statechart(cd.get_default_class(), cd.globals, w)
+
+
+    w.writeln("fn main() {")
+    w.indent()
 
     for v in variants:
-        pass
+        w.writeln("// Test variant")
+        w.writeln("let mut sc: Statechart = Default::default();")
+        for i in v.input:
+            if len(i.events) > 1:
+                raise Exception("Multiple simultaneous input events not supported")
+            elif len(i.events) == 0:
+                raise Exception("Test declares empty bag of input events - not supported")
+            e = i.events[0]
+
+            w.writeln("println!(\"time is now %s\");" % i.timestamp.render())
+            w.writeln("sc.fair_step(Some(Event::%s));" % e.name)
+        pass
+
+    w.dedent()
+    w.writeln("}")

+ 15 - 57
src/sccd/util/indenting_writer.py

@@ -1,64 +1,22 @@
 import sys
 
 class IndentingWriter:
+    def __init__(self, spaces=2, out=sys.stdout, initial=0):
+        self.spaces = spaces
+        self.out = out
+        self.state = initial
 
-  def __init__(self, out = sys.stdout):
-    self.out = out
-    self.indentLevel = 0
-    self.indentSpace = "    "
-    self.first_write = True
+    def indent(self):
+        self.state += self.spaces
 
-  def write(self, text = ""):
-    if self.first_write :
-      self.first_write = False
-      if text == "":
-        self.out.write(self.indentLevel*self.indentSpace)
-      else:
-        self.out.write(self.indentLevel*self.indentSpace + text)  
-    else:
-      if text == "":
-        self.out.write("\n" + self.indentLevel*self.indentSpace)
-      else:
-        self.out.write("\n" + self.indentLevel*self.indentSpace + text)
-  
-  def extendWrite(self, text = ""):
-    self.out.write(text)
-        
-  def indent(self):
-    self.indentLevel+=1
+    def dedent(self):
+        self.state -= self.spaces
 
-  def dedent(self):
-    self.indentLevel-=1
+    def writeln(self, s=""):
+        if s == "":
+            self.out.write('\n')
+        else:
+            self.out.write(' '*self.state + s + '\n')
 
-  def writeCodeCorrectIndent(self, body):
-    lines = body.split('\n')
-    while( len(lines) > 0 and lines[-1].strip() == "") :
-      del(lines[-1])
-  
-    index = 0;
-    while( len(lines) > index and lines[index].strip() == "") :    
-      index += 1
-      
-    if index >= len(lines) :
-      return
-    #first index where valid code is present
-    to_strip_index = len(lines[index].rstrip()) - len(lines[index].strip()) 
-    indent_type = NOT_SET;
-      
-    while index < len(lines):
-      strip_part = lines[index][:to_strip_index]
-      
-      if( ('\t' in strip_part and ' ' in strip_part) or
-        (indent_type == SPACES_USED and '\t' in strip_part) or
-        (indent_type == TABS_USED and ' ' in strip_part)
-      ) :
-        raise Exception("Mixed tab and space indentation!")
-      
-      if indent_type == NOT_SET :
-        if ' ' in strip_part :
-          indent_type = SPACES_USED
-        elif '\t' in strip_part :
-          indent_type = TABS_USED
-          
-      self.write(lines[index][to_strip_index:])
-      index += 1
+    def write(self, s):
+        self.out.write(' '*self.state + s)

+ 0 - 119
src/sccd/util/utils.py

@@ -1,119 +0,0 @@
-from sys import stdout
-
-from sccd.compiler.compiler_exceptions import CodeBlockException
-
-class Logger(object):
-	verbose = 0 #-1= no output
-				#0 = only errors
-				#1 = only warnings and errors
-				#2 = all output
-				
-	@staticmethod   
-	def showError(error):
-		if(Logger.verbose > -1) :
-			print("ERROR : " + error)
-				
-	@staticmethod
-	def showWarning(warning):
-		if(Logger.verbose > 0) :
-			print("WARNING : " + warning)
-			
-	@staticmethod	
-	def showInfo(info):
-		if(Logger.verbose > 1) :
-			print("INFO : " + info)
-
-#######################
-
-class Enum():	
-	def __init__(self, *entries):
-		self._keys = entries
-		self._map = {}
-		for v,k in enumerate(self._keys) :
-			self._map[k] = v
-			
-	def __getattr__(self, name):
-		return self._map[name]
-			
-	def name_of(self, index):
-		return self._keys[index]
-
-#######################
-
-NOT_SET = 0
-SPACES_USED = 1
-TABS_USED = 2
-
-class FormattedWriter:
-
-	def __init__(self, out = stdout):
-		self.out = out
-		self.indentLevel = 0
-		self.indentSpace = "    "
-		self.first_write = True
-
-	def write(self, text = ""):
-		if self.first_write :
-			self.first_write = False
-			if text == "":
-				self.out.write(self.indentLevel*self.indentSpace)
-			else:
-				self.out.write(self.indentLevel*self.indentSpace + text)  
-		else:
-			if text == "":
-				self.out.write("\n" + self.indentLevel*self.indentSpace)
-			else:
-				self.out.write("\n" + self.indentLevel*self.indentSpace + text)
-	
-	def extendWrite(self, text = ""):
-		self.out.write(text)
-				
-	def indent(self):
-		self.indentLevel+=1
-
-	def dedent(self):
-		self.indentLevel-=1
-
-	def writeCodeCorrectIndent(self, body):
-		lines = body.split('\n')
-		while( len(lines) > 0 and lines[-1].strip() == "") :
-			del(lines[-1])
-	
-		index = 0;
-		while( len(lines) > index and lines[index].strip() == "") :	   
-			index += 1
-			
-		if index >= len(lines) :
-			return
-		#first index where valid code is present
-		to_strip_index = len(lines[index].rstrip()) - len(lines[index].strip()) 
-		indent_type = NOT_SET;
-			
-		while index < len(lines):
-			strip_part = lines[index][:to_strip_index]
-			
-			if( ('\t' in strip_part and ' ' in strip_part) or
-				(indent_type == SPACES_USED and '\t' in strip_part) or
-				(indent_type == TABS_USED and ' ' in strip_part)
-			) :
-				raise CodeBlockException("Mixed tab and space indentation!")
-			
-			if indent_type == NOT_SET :
-				if ' ' in strip_part :
-					indent_type = SPACES_USED
-				elif '\t' in strip_part :
-					indent_type = TABS_USED
-					
-			self.write(lines[index][to_strip_index:])
-			index += 1
-
-
-class FileWriter(FormattedWriter):
-
-	def __init__(self, filename):
-		FormattedWriter.__init__(self, open(filename, 'w'))
-
-	def close(self):
-		self.out.close()
-
-#######################