| summaryrefslogtreecommitdiff | 
diff options
| author | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2020-11-01 01:08:13 +0100 | 
|---|---|---|
| committer | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2020-11-01 01:08:13 +0100 | 
| commit | cab99a7f9be5a5a08cf66f1226a384a180098c69 (patch) | |
| tree | 937b6d487c87efaf9ccb56981f763c239220e2f5 /src | |
| parent | 6ac2d50fc176b0c77890b6ab6ec4b0db4e4d08a2 (diff) | |
First shot at option+event player inputs.
Diffstat (limited to 'src')
16 files changed, 1019 insertions, 49 deletions
| diff --git a/src/core/src/tonkadur/fate/v1/lang/InputEvent.java b/src/core/src/tonkadur/fate/v1/lang/InputEvent.java new file mode 100644 index 0000000..17d6a48 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/InputEvent.java @@ -0,0 +1,181 @@ +package tonkadur.fate.v1.lang; + +import java.util.ArrayList; +import java.util.List; + +import tonkadur.functional.Merge; + +import tonkadur.parser.Context; +import tonkadur.parser.Location; +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.meta.DeclaredEntity; + +import tonkadur.fate.v1.lang.type.Type; + +public class InputEvent extends DeclaredEntity +{ +   protected static final InputEvent ANY; + +   static +   { +      ANY = +         new InputEvent +         ( +            Origin.BASE_LANGUAGE, +            new ArrayList<Type>(), +            /* +             * Use of a space necessary to avoid conflicting with a user created +             * type. +             */ +            "undetermined input event" +         ); +   } + +   public static InputEvent value_on_missing () +   { +      return ANY; +   } + +   @Override +   public /* static */ String get_type_name () +   { +      return "InputEvent"; +   } + + +   /***************************************************************************/ +   /**** MEMBERS **************************************************************/ +   /***************************************************************************/ +   protected final List<Type> signature; + +   /***************************************************************************/ +   /**** PUBLIC ***************************************************************/ +   /***************************************************************************/ + +   /**** Constructors *********************************************************/ +   public InputEvent +   ( +      final Origin origin, +      final List<Type> signature, +      final String name +   ) +   { +      super(origin, name); + +      this.signature = signature; +   } + +   /**** Accessors ************************************************************/ +   public List<Type> get_signature () +   { +      return signature; +   } + +   @Override +   public DeclaredEntity generate_comparable_to (final DeclaredEntity de) +   { +      final List<Type> new_signature; +      final InputEvent e; + +      if (!(de instanceof InputEvent)) +      { +         return ANY; +      } + +      e = (InputEvent) de; + +      if (signature.size() != e.signature.size()) +      { +         return ANY; +      } + +      new_signature = +         new Merge<Type, Type, Type>() +         { +            @Override +            protected Type lambda (final Type a, final Type b) +            { +               return (Type) a.generate_comparable_to(b); +            } +         }.merge(signature, e.signature); + +      return new InputEvent(origin, new_signature, name); +   } + +   /**** Misc. ****************************************************************/ +   @Override +   public boolean is_incompatible_with_declaration (final DeclaredEntity de) +   { +      if (de instanceof InputEvent) +      { +         final InputEvent e; + +         e = (InputEvent) de; + +         if (signature.size() == e.signature.size()) +         { +            final List<Boolean> compatibility_result; + +            /* +             * Basically, the events are compatible if, and only if, the old +             * signature is as least as restrictive as the new one. +             */ +            compatibility_result = +               ( +                  new Merge<Type, Type, Boolean>() +                  { +                     @Override +                     protected Boolean lambda (final Type a, final Type b) +                     { +                        return +                           new Boolean(a.can_be_used_as(b)); +                     } +                  }.merge(signature, e.signature) +               ); + +            return compatibility_result.contains(Boolean.TRUE); +         } +      } + +      return true; +   } + +   @Override +   public String toString () +   { +      final StringBuilder sb = new StringBuilder(); + +      sb.append("("); +      sb.append(get_type_name()); +      sb.append(" "); +      sb.append(name); + +      if (!signature.isEmpty()) +      { +         boolean first_argument; + +         sb.append(": "); + +         first_argument = true; + +         for (final Type type: signature) +         { +            if (first_argument) +            { +               first_argument = false; +            } +            else +            { +               sb.append(" -> "); +            } + +            sb.append(type.get_name()); +         } +      } + +      sb.append(")"); + +      return sb.toString(); +   } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/World.java b/src/core/src/tonkadur/fate/v1/lang/World.java index 047f1d5..c813312 100644 --- a/src/core/src/tonkadur/fate/v1/lang/World.java +++ b/src/core/src/tonkadur/fate/v1/lang/World.java @@ -42,6 +42,7 @@ public class World        extension_first_level_instructions;     protected final DeclarationCollection<Event> event_collection; +   protected final DeclarationCollection<InputEvent> input_event_collection;     protected final DeclarationCollection<Sequence> sequence_collection;     protected final DeclarationCollection<TextEffect> text_effect_collection;     protected final DeclarationCollection<Type> type_collection; @@ -69,6 +70,8 @@ public class World        event_collection =           new DeclarationCollection<Event>(Event.value_on_missing()); +      input_event_collection = +         new DeclarationCollection<InputEvent>(InputEvent.value_on_missing());        sequence_collection = new DeclarationCollection<Sequence>(null);        text_effect_collection = @@ -162,6 +165,11 @@ public class World        return event_collection;     } +   public DeclarationCollection<InputEvent> input_events () +   { +      return input_event_collection; +   } +     public DeclarationCollection<Sequence> sequences ()     {        return sequence_collection; @@ -241,6 +249,13 @@ public class World        sb.append(System.lineSeparator());        sb.append(System.lineSeparator()); +      sb.append(System.lineSeparator()); +      sb.append("Input Events: "); +      sb.append(System.lineSeparator()); +      sb.append(input_event_collection.toString()); +      sb.append(System.lineSeparator()); +      sb.append(System.lineSeparator()); +        sb.append("Text Effects: ");        sb.append(System.lineSeparator());        sb.append(text_effect_collection.toString()); diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/PlayerChoice.java b/src/core/src/tonkadur/fate/v1/lang/instruction/PlayerChoice.java index 1f40c8a..738fe71 100644 --- a/src/core/src/tonkadur/fate/v1/lang/instruction/PlayerChoice.java +++ b/src/core/src/tonkadur/fate/v1/lang/instruction/PlayerChoice.java @@ -4,19 +4,15 @@ import java.util.List;  import tonkadur.parser.Origin; -import tonkadur.fate.v1.lang.type.Type; -  import tonkadur.fate.v1.lang.meta.InstructionVisitor;  import tonkadur.fate.v1.lang.meta.Instruction; -import tonkadur.fate.v1.lang.meta.RichTextNode;  public class PlayerChoice extends Instruction  {     /***************************************************************************/     /**** MEMBERS **************************************************************/     /***************************************************************************/ -   protected final RichTextNode text; -   protected final List<Instruction> effects; +   protected final List<Instruction> entries;     /***************************************************************************/     /**** PUBLIC ***************************************************************/ @@ -25,17 +21,14 @@ public class PlayerChoice extends Instruction     public PlayerChoice     (        final Origin origin, -      final RichTextNode text, -      final List<Instruction> effects +      final List<Instruction> entries     )     {        super(origin); -      this.text = text; -      this.effects = effects; +      this.entries = entries;     } -     /**** Accessors ************************************************************/     @Override     public void get_visited_by (final InstructionVisitor iv) @@ -44,14 +37,9 @@ public class PlayerChoice extends Instruction        iv.visit_player_choice(this);     } -   public RichTextNode get_text () -   { -      return text; -   } - -   public List<Instruction> get_effects () +   public List<Instruction> get_entries ()     { -      return effects; +      return entries;     }     /**** Misc. ****************************************************************/ @@ -60,14 +48,14 @@ public class PlayerChoice extends Instruction     {        final StringBuilder sb = new StringBuilder(); -      sb.append("(PlayerChoice"); +      sb.append("(PlayerChoice "); +        sb.append(System.lineSeparator()); -      sb.append(text.toString()); -      for (final Instruction effect: effects) +      for (final Instruction entry: entries)        { +         sb.append(entry.toString());           sb.append(System.lineSeparator()); -         sb.append(effect.toString());        }        sb.append(")"); diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/PlayerInput.java b/src/core/src/tonkadur/fate/v1/lang/instruction/PlayerInput.java new file mode 100644 index 0000000..a1efed4 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/instruction/PlayerInput.java @@ -0,0 +1,134 @@ +package tonkadur.fate.v1.lang.instruction; + +import java.util.ArrayList; +import java.util.List; + +import tonkadur.parser.Origin; +import tonkadur.parser.ParsingError; + +import tonkadur.fate.v1.lang.InputEvent; + +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.meta.InstructionVisitor; +import tonkadur.fate.v1.lang.meta.Instruction; +import tonkadur.fate.v1.lang.meta.Computation; +import tonkadur.fate.v1.lang.meta.RecurrentChecks; + +public class PlayerInput extends Instruction +{ +   /***************************************************************************/ +   /**** MEMBERS **************************************************************/ +   /***************************************************************************/ +   protected final InputEvent input_event; +   protected final List<Computation> params; +   protected final List<Instruction> effects; + +   /***************************************************************************/ +   /**** PROTECTED ************************************************************/ +   /***************************************************************************/ +   /**** Constructors *********************************************************/ +   protected PlayerInput +   ( +      final Origin origin, +      final InputEvent input_event, +      final List<Computation> params, +      final List<Instruction> effects +   ) +   { +      super(origin); + +      this.input_event = input_event; +      this.params = params; +      this.effects = effects; +   } + +   /***************************************************************************/ +   /**** PUBLIC ***************************************************************/ +   /***************************************************************************/ +   /**** Constructors *********************************************************/ +   public PlayerInput +   ( +      final Origin origin, +      final InputEvent input_event, +      final List<Instruction> effects +   ) +   { +      super(origin); + +      this.input_event = input_event; +      this.params = new ArrayList<Computation>(); +      this.effects = effects; +   } + +   public static PlayerInput build +   ( +      final Origin origin, +      final InputEvent event, +      final List<Computation> parameters, +      final List<Instruction> effects +   ) +   throws ParsingError +   { +      RecurrentChecks.assert_computations_matches_signature +      ( +         origin, +         parameters, +         event.get_signature() +      ); + +      return new PlayerInput(origin, event, parameters, effects); +   } + +   /**** Accessors ************************************************************/ +   @Override +   public void get_visited_by (final InstructionVisitor iv) +   throws Throwable +   { +      iv.visit_player_input(this); +   } + +   public InputEvent get_input_event () +   { +      return input_event; +   } + +   public List<Computation> get_parameters () +   { +      return params; +   } + +   public List<Instruction> get_effects () +   { +      return effects; +   } + +   /**** Misc. ****************************************************************/ +   @Override +   public String toString () +   { +      final StringBuilder sb = new StringBuilder(); + +      sb.append("(PlayerInput ("); +      sb.append(System.lineSeparator()); +      sb.append(input_event.toString()); + +      for (final Computation param: params) +      { +         sb.append(" "); +         sb.append(param.toString()); +      } + +      sb.append(")"); + +      for (final Instruction effect: effects) +      { +         sb.append(System.lineSeparator()); +         sb.append(effect.toString()); +      } + +      sb.append(")"); + +      return sb.toString(); +   } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/PlayerChoiceList.java b/src/core/src/tonkadur/fate/v1/lang/instruction/PlayerOption.java index 79a2570..d6db1e4 100644 --- a/src/core/src/tonkadur/fate/v1/lang/instruction/PlayerChoiceList.java +++ b/src/core/src/tonkadur/fate/v1/lang/instruction/PlayerOption.java @@ -4,42 +4,54 @@ import java.util.List;  import tonkadur.parser.Origin; +import tonkadur.fate.v1.lang.type.Type; +  import tonkadur.fate.v1.lang.meta.InstructionVisitor;  import tonkadur.fate.v1.lang.meta.Instruction; +import tonkadur.fate.v1.lang.meta.RichTextNode; -public class PlayerChoiceList extends Instruction +public class PlayerOption extends Instruction  {     /***************************************************************************/     /**** MEMBERS **************************************************************/     /***************************************************************************/ -   protected final List<Instruction> choices; +   protected final RichTextNode text; +   protected final List<Instruction> effects;     /***************************************************************************/     /**** PUBLIC ***************************************************************/     /***************************************************************************/     /**** Constructors *********************************************************/ -   public PlayerChoiceList +   public PlayerOption     (        final Origin origin, -      final List<Instruction> choices +      final RichTextNode text, +      final List<Instruction> effects     )     {        super(origin); -      this.choices = choices; +      this.text = text; +      this.effects = effects;     } +     /**** Accessors ************************************************************/     @Override     public void get_visited_by (final InstructionVisitor iv)     throws Throwable     { -      iv.visit_player_choice_list(this); +      iv.visit_player_option(this);     } -   public List<Instruction> get_choices () +   public RichTextNode get_text ()     { -      return choices; +      return text; +   } + +   public List<Instruction> get_effects () +   { +      return effects;     }     /**** Misc. ****************************************************************/ @@ -48,14 +60,15 @@ public class PlayerChoiceList extends Instruction     {        final StringBuilder sb = new StringBuilder(); -      sb.append("(PlayerChoiceList "); - +      sb.append("(PlayerOption (");        sb.append(System.lineSeparator()); +      sb.append(text.toString()); +      sb.append(")"); -      for (final Instruction choice: choices) +      for (final Instruction effect: effects)        { -         sb.append(choice.toString());           sb.append(System.lineSeparator()); +         sb.append(effect.toString());        }        sb.append(")"); diff --git a/src/core/src/tonkadur/fate/v1/lang/meta/InstructionVisitor.java b/src/core/src/tonkadur/fate/v1/lang/meta/InstructionVisitor.java index a3038ac..a672f3c 100644 --- a/src/core/src/tonkadur/fate/v1/lang/meta/InstructionVisitor.java +++ b/src/core/src/tonkadur/fate/v1/lang/meta/InstructionVisitor.java @@ -122,7 +122,10 @@ public interface InstructionVisitor     public void visit_player_choice (final PlayerChoice n)     throws Throwable; -   public void visit_player_choice_list (final PlayerChoiceList n) +   public void visit_player_option (final PlayerOption n) +   throws Throwable; + +   public void visit_player_input (final PlayerInput n)     throws Throwable;     public void visit_remove_all_of_element (final RemoveAllOfElement n) diff --git a/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 b/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 index c5f073d..b1dbd75 100644 --- a/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 +++ b/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 @@ -38,6 +38,7 @@ DECLARE_ALIAS_TYPE_KW:  DECLARE_DICT_TYPE_KW: L_PAREN     ('declare'|'define'|'def')US('dict'|('struct''ure'?))(US'type')? SEP+;  DECLARE_EVENT_TYPE_KW: L_PAREN ('declare'|'define'|'def')US'event'(US'type')? SEP+; +DECLARE_INPUT_EVENT_TYPE_KW: L_PAREN ('declare'|'define'|'def')US'input'US'event'(US'type')? SEP+;  DECLARE_TEXT_EFFECT_KW: L_PAREN ('declare'|'define'|'def')US'text'US'effect' SEP+;  DECLARE_VARIABLE_KW: L_PAREN 'global' SEP+;  LOCAL_KW: L_PAREN 'local' SEP+; @@ -113,6 +114,8 @@ IMP_PUSH_LEFT_KW: L_PAREN 'push'US'left!' SEP+;  PUSH_RIGHT_KW: L_PAREN 'push'US'right' SEP+;  IMP_PUSH_RIGHT_KW: L_PAREN 'push'US'right!' SEP+;  PLAYER_CHOICE_KW: L_PAREN ('choice'|'user'US'choice'|'player'US'choice') SEP+; +PLAYER_OPTION_KW: L_PAREN ('option'|'user'US'option'|'player'US'option') SEP+; +PLAYER_EVENT_KW: L_PAREN ('event'|'user'US'event'|'player'US'event') SEP+;  PLUS_KW: L_PAREN ('plus'|'+') SEP+;  POWER_KW: L_PAREN ('power'|'^'|'**'|'pow') SEP+;  RANGE_KW: L_PAREN 'range' SEP+; diff --git a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 index d4798a0..4859c85 100644 --- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 +++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 @@ -367,6 +367,52 @@ first_level_fate_instr:        WORLD.events().add(new_event);     } +   | DECLARE_INPUT_EVENT_TYPE_KW new_reference_name WS* R_PAREN +   { +      final Origin start_origin; +      final InputEvent new_event; + +      start_origin = +         CONTEXT.get_origin_at +         ( +            ($DECLARE_INPUT_EVENT_TYPE_KW.getLine()), +            ($DECLARE_INPUT_EVENT_TYPE_KW.getCharPositionInLine()) +         ); + +      new_event = +         new InputEvent +         ( +            start_origin, +            new ArrayList<Type>(), +            ($new_reference_name.result) +         ); + +      WORLD.input_events().add(new_event); +   } + +   | DECLARE_INPUT_EVENT_TYPE_KW new_reference_name WS+ type_list WS* R_PAREN +   { +      final Origin start_origin; +      final InputEvent new_event; + +      start_origin = +         CONTEXT.get_origin_at +         ( +            ($DECLARE_INPUT_EVENT_TYPE_KW.getLine()), +            ($DECLARE_INPUT_EVENT_TYPE_KW.getCharPositionInLine()) +         ); + +      new_event = +         new InputEvent +         ( +            start_origin, +            ($type_list.result), +            ($new_reference_name.result) +         ); + +      WORLD.input_events().add(new_event); +   } +     | REQUIRE_KW WORD WS* R_PAREN     { @@ -1762,7 +1808,7 @@ returns [Instruction result]     | PLAYER_CHOICE_KW player_choice_list WS* R_PAREN     {        $result = -         new PlayerChoiceList +         new PlayerChoice           (              CONTEXT.get_origin_at              ( @@ -1953,7 +1999,7 @@ returns [List<Instruction> result]  player_choice  returns [Instruction result]  : -   start_p=L_PAREN WS* +   PLAYER_OPTION_KW        L_PAREN WS* paragraph WS* R_PAREN WS+        {           HIERARCHICAL_VARIABLES.push(new ArrayList()); @@ -1969,18 +2015,91 @@ returns [Instruction result]     R_PAREN     {        $result = -         new PlayerChoice +         new PlayerOption           (              CONTEXT.get_origin_at              ( -               ($start_p.getLine()), -               ($start_p.getCharPositionInLine()) +               ($PLAYER_OPTION_KW.getLine()), +               ($PLAYER_OPTION_KW.getCharPositionInLine())              ),              ($paragraph.result),              ($general_fate_sequence.result)           );     } +   | PLAYER_EVENT_KW +      L_PAREN WS* WORD WS* R_PAREN WS+ +      { +         HIERARCHICAL_VARIABLES.push(new ArrayList()); +      } +      general_fate_sequence +      { +         for (final String s: HIERARCHICAL_VARIABLES.pop()) +         { +            LOCAL_VARIABLES.peekFirst().remove(s); +         } +      } +      WS* +   R_PAREN +   { +      final Origin origin; +      final InputEvent event; + +      origin = +         CONTEXT.get_origin_at +         ( +            ($PLAYER_EVENT_KW.getLine()), +            ($PLAYER_EVENT_KW.getCharPositionInLine()) +         ); + +      event = WORLD.input_events().get(origin, ($WORD.text)); + +      $result = +         new PlayerInput +         ( +            origin, +            event, +            ($general_fate_sequence.result) +         ); +   } + +   | PLAYER_EVENT_KW +      L_PAREN WS* WORD WS+ value_list WS* R_PAREN WS+ +      { +         HIERARCHICAL_VARIABLES.push(new ArrayList()); +      } +      general_fate_sequence +      { +         for (final String s: HIERARCHICAL_VARIABLES.pop()) +         { +            LOCAL_VARIABLES.peekFirst().remove(s); +         } +      } +      WS* +   R_PAREN +   { +      final Origin origin; +      final InputEvent event; + +      origin = +         CONTEXT.get_origin_at +         ( +            ($PLAYER_EVENT_KW.getLine()), +            ($PLAYER_EVENT_KW.getCharPositionInLine()) +         ); + +      event = WORLD.input_events().get(origin, ($WORD.text)); + +      $result = +         PlayerInput.build +         ( +            origin, +            event, +            ($value_list.result), +            ($general_fate_sequence.result) +         ); +   } +     | IF_KW           non_text_value WS+           player_choice_list WS* diff --git a/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/ComputationCompiler.java b/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/ComputationCompiler.java index 25f48e8..fa4ae49 100644 --- a/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/ComputationCompiler.java +++ b/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/ComputationCompiler.java @@ -831,7 +831,11 @@ implements tonkadur.fate.v1.lang.meta.ComputationVisitor                    result_as_address,                    new IfElseComputation                    ( -                     Operation.less_than(result_as_computation, operand), +                     Operation.less_than +                     ( +                        result_as_computation, +                        operand +                     ),                       result_as_computation,                       operand                    ) diff --git a/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/InstructionCompiler.java b/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/InstructionCompiler.java index ada630b..d27f865 100644 --- a/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/InstructionCompiler.java +++ b/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/InstructionCompiler.java @@ -29,6 +29,7 @@ import tonkadur.wyrd.v1.lang.computation.GetLastChoiceIndex;  import tonkadur.wyrd.v1.lang.computation.ValueOf;  import tonkadur.wyrd.v1.lang.instruction.AddChoice; +import tonkadur.wyrd.v1.lang.instruction.AddEventInput;  import tonkadur.wyrd.v1.lang.instruction.Assert;  import tonkadur.wyrd.v1.lang.instruction.Display;  import tonkadur.wyrd.v1.lang.instruction.End; @@ -2325,9 +2326,9 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor     }     @Override -   public void visit_player_choice +   public void visit_player_option     ( -      final tonkadur.fate.v1.lang.instruction.PlayerChoice n +      final tonkadur.fate.v1.lang.instruction.PlayerOption n     )     throws Throwable     { @@ -2466,9 +2467,172 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor     }     @Override -   public void visit_player_choice_list +   public void visit_player_input     ( -      final tonkadur.fate.v1.lang.instruction.PlayerChoiceList n +      final tonkadur.fate.v1.lang.instruction.PlayerInput n +   ) +   throws Throwable +   { +      /* +       * Fate: (player_choice label i0) +       * +       * Wyrd (add_choice label i0) +       */ +      final List<Instruction> to_next, labels_only; +      final List<ComputationCompiler> params_cc; +      final List<Computation> params; +      final String start_of_effect, end_of_effect; + +      to_next = new ArrayList<Instruction>(); +      labels_only = new ArrayList<Instruction>(); +      params = new ArrayList<Computation>(); +      params_cc = new ArrayList<ComputationCompiler>(); + +      start_of_effect = compiler.assembler().generate_label("<choice#start>"); +      end_of_effect = compiler.assembler().generate_label("<choice#end>"); + +      for +      ( +         final tonkadur.fate.v1.lang.meta.Computation param: n.get_parameters() +      ) +      { +         final ComputationCompiler cc; + +         cc = new ComputationCompiler(compiler); + +         param.get_visited_by(cc); + +         if (cc.has_init()) +         { +            result.add(cc.get_init()); +         } + +         params.add(cc.get_computation()); +      } + +      labels_only.add +      ( +         new AddEventInput(n.get_input_event().get_name(), params) +      ); + +      for (final ComputationCompiler cc: params_cc) +      { +         cc.release_registers(labels_only); +      } + +      labels_only.add +      ( +         new SetPC(compiler.assembler().get_label_constant(end_of_effect)) +      ); + +      result.add +      ( +         If.generate +         ( +            compiler.registers(), +            compiler.assembler(), +            Operation.equals +            ( +               compiler.registers().get_choice_number_holder().get_value(), +               new Constant(Type.INT, "-2") +            ), +            compiler.assembler().merge(labels_only) +         ) +      ); + + +      to_next.add +      ( +         new SetValue +         ( +            compiler.registers().get_choice_number_holder().get_address(), +            Operation.plus +            ( +               compiler.registers().get_choice_number_holder().get_value(), +               Constant.ONE +            ) +         ) +      ); + +      to_next.add +      ( +         new SetPC(compiler.assembler().get_label_constant(end_of_effect)) +      ); + +      result.add +      ( +         compiler.assembler().mark_after +         ( +            If.generate +            ( +               compiler.registers(), +               compiler.assembler(), +               Operation.not +               ( +                  Operation.equals +                  ( +                     compiler.registers().get_choice_number_holder().get_value(), +                     new GetLastChoiceIndex() +                  ) +               ), +               compiler.assembler().merge(to_next) +            ), +            start_of_effect +         ) +      ); + +      result.add +      ( +         new SetValue +         ( +            compiler.registers().get_rand_mode_holder().get_address(), +            new Constant(Type.INT, "0") +         ) +      ); + +      result.add +      ( +         Clear.generate +         ( +            compiler.registers(), +            compiler.assembler(), +            new Size +            ( +               compiler.registers().get_rand_value_holder().get_address() +            ), +            compiler.registers().get_rand_value_holder().get_address() +         ) +      ); + +      compiler.registers().push_hierarchical_instruction_level(); +      for +      ( +         final tonkadur.fate.v1.lang.meta.Instruction fate_instruction: +            n.get_effects() +      ) +      { +         fate_instruction.get_visited_by(this); +      } +      compiler.registers().pop_hierarchical_instruction_level(result); + +      result.add +      ( +         compiler.assembler().mark_after +         ( +            new SetPC +            ( +               compiler.assembler().get_context_label_constant("choices") +            ), +            end_of_effect +         ) +      ); +   } + + +   @Override +   public void visit_player_choice +   ( +      final tonkadur.fate.v1.lang.instruction.PlayerChoice n     )     throws Throwable     { @@ -2516,7 +2680,7 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor        for        (           final tonkadur.fate.v1.lang.meta.Instruction fate_instruction: -            n.get_choices() +            n.get_entries()        )        {           fate_instruction.get_visited_by(this); diff --git a/src/core/src/tonkadur/wyrd/v1/compiler/util/BinarySearch.java b/src/core/src/tonkadur/wyrd/v1/compiler/util/BinarySearch.java index 44106bf..a8efd31 100644 --- a/src/core/src/tonkadur/wyrd/v1/compiler/util/BinarySearch.java +++ b/src/core/src/tonkadur/wyrd/v1/compiler/util/BinarySearch.java @@ -263,4 +263,207 @@ public class BinarySearch        return assembler.merge(result);     } + +   public static Instruction generate +   ( +      final RegisterManager registers, +      final InstructionManager assembler, +      final Computation sort_fun, +      final Computation target, +      final Computation collection_size, +      final Address collection, +      final Address result_was_found, +      final Address result_index, +      final List<Computation> sort_fun_extra_params +   ) +   { +      final List<Instruction> result, while_body; +      final Register bot, top, midval, cmp; +      final Type element_type; +      final Computation value_of_result_index; + +      result = new ArrayList<Instruction>(); +      while_body = new ArrayList<Instruction>(); + +      element_type = target.get_type(); + +      bot = registers.reserve(Type.INT, result); +      top = registers.reserve(Type.INT, result); +      midval = registers.reserve(element_type, result); +      cmp = registers.reserve(Type.INT, result); + +      value_of_result_index = new ValueOf(result_index); + +      result.add(new SetValue(result_index, Constant.ZERO)); +      result.add(new SetValue(result_was_found, Constant.FALSE)); +      result.add(new SetValue(bot.get_address(), Constant.ZERO)); +      result.add +      ( +         new SetValue +         ( +            top.get_address(), +            Operation.minus(collection_size, Constant.ONE) +         ) +      ); + +      /* +       *    (set result_index +       *       (+ +       *          (var .bot) +       *          (cast int +       *             (/ +       *                (cast float +       *                   (- (var .top) (var .bot)) +       *                ) +       *                2.0 +       *             ) +       *          ) +       *       ) +       *    ) +       */ +      while_body.add +      ( +         new SetValue +         ( +            result_index, +            Operation.plus +            ( +               bot.get_value(), +               new Cast +               ( +                  Operation.divide +                  ( +                     new Cast +                     ( +                        Operation.minus(top.get_value(), bot.get_value()), +                        Type.FLOAT +                     ), +                     new Constant(Type.FLOAT, "2.0") +                  ), +                  Type.INT +               ) +            ) +         ) +      ); + +      /* (set .midval (var collection[.result_index])) */ +      while_body.add +      ( +         new SetValue +         ( +            midval.get_address(), +            new ValueOf +            ( +               new RelativeAddress +               ( +                  collection, +                  new Cast(value_of_result_index, Type.STRING), +                  element_type +               ) +            ) +         ) +      ); + +      while_body.add +      ( +         LambdaEvaluation.generate +         ( +            registers, +            assembler, +            sort_fun, +            cmp.get_address(), +            sort_fun_extra_params +         ) +      ); + +      /* +       *    <ifelse +       *       (< (var .midval) element) +       * +       *       (set .bot (+ (var result_index) 1)) +       * +       *       <ifelse +       *          (> (var .midval) element) +       * +       *          (set .top (- (var result_index) 1)) +       * +       *          (set result_found true) +       *       > +       *    > +       */ +      while_body.add +      ( +         IfElse.generate +         ( +            registers, +            assembler, +            Operation.less_than(cmp.get_value(), Constant.ZERO), +            new SetValue +            ( +               bot.get_address(), +               Operation.plus(value_of_result_index, Constant.ONE) +            ), +            IfElse.generate +            ( +               registers, +               assembler, +               Operation.greater_than(cmp.get_value(), Constant.ZERO), +               new SetValue +               ( +                  top.get_address(), +                  Operation.minus(value_of_result_index, Constant.ONE) +               ), +               new SetValue(result_was_found, Constant.TRUE) +            ) +         ) +      ); + +      result.add +      ( +         While.generate +         ( +            registers, +            assembler, +            Operation.and +            ( +               Operation.not(new ValueOf(result_was_found)), +               Operation.less_equal_than(bot.get_value(), top.get_value()) +            ), +            assembler.merge(while_body) +         ) +      ); + +      /* Without this, you'll replace the value and move it to the right, +       * regardless of where you 'target' stands in relation to it. +       */ +      result.add +      ( +         If.generate +         ( +            registers, +            assembler, +            Operation.and +            ( +               Operation.and +               ( +                  Operation.not(new ValueOf(result_was_found)), +                  Operation.greater_than(target, midval.get_value()) +               ), +               Operation.greater_than(collection_size, Constant.ZERO) +            ), +            new SetValue +            ( +               result_index, +               Operation.plus(value_of_result_index, Constant.ONE) +            ) +         ) +      ); + +      registers.release(bot, result); +      registers.release(top, result); +      registers.release(midval, result); +      registers.release(cmp, result); + +      return assembler.merge(result); +   }  } diff --git a/src/core/src/tonkadur/wyrd/v1/compiler/util/PopElement.java b/src/core/src/tonkadur/wyrd/v1/compiler/util/PopElement.java index 3da9a89..6a436a6 100644 --- a/src/core/src/tonkadur/wyrd/v1/compiler/util/PopElement.java +++ b/src/core/src/tonkadur/wyrd/v1/compiler/util/PopElement.java @@ -68,11 +68,14 @@ public class PopElement           new SetValue           (              element_holder, -            new RelativeAddress +            new ValueOf              ( -               collection, -               new Cast(target_index, Type.STRING), -               ((PointerType) element_holder.get_type()).get_target_type() +               new RelativeAddress +               ( +                  collection, +                  new Cast(target_index, Type.STRING), +                  ((PointerType) element_holder.get_type()).get_target_type() +               )              )           )        ); diff --git a/src/core/src/tonkadur/wyrd/v1/compiler/util/Sort.java b/src/core/src/tonkadur/wyrd/v1/compiler/util/Sort.java new file mode 100644 index 0000000..200f7ef --- /dev/null +++ b/src/core/src/tonkadur/wyrd/v1/compiler/util/Sort.java @@ -0,0 +1,46 @@ +package tonkadur.wyrd.v1.compiler.util; + +import java.util.List; +import java.util.ArrayList; +import java.util.Collections; + +import tonkadur.wyrd.v1.lang.Register; + +import tonkadur.wyrd.v1.lang.type.Type; +import tonkadur.wyrd.v1.lang.type.MapType; + +import tonkadur.wyrd.v1.lang.meta.Instruction; +import tonkadur.wyrd.v1.lang.meta.Computation; + +import tonkadur.wyrd.v1.lang.computation.Address; +import tonkadur.wyrd.v1.lang.computation.Cast; +import tonkadur.wyrd.v1.lang.computation.Constant; +import tonkadur.wyrd.v1.lang.computation.Operation; +import tonkadur.wyrd.v1.lang.computation.RelativeAddress; +import tonkadur.wyrd.v1.lang.computation.Size; +import tonkadur.wyrd.v1.lang.computation.ValueOf; + +import tonkadur.wyrd.v1.lang.instruction.SetValue; +import tonkadur.wyrd.v1.lang.instruction.Remove; + +import tonkadur.wyrd.v1.compiler.util.registers.RegisterManager; + +public class Sort +{ +   /* Utility Class */ +   private Sort () {} + +   public static Instruction generate +   ( +      final RegisterManager registers, +      final InstructionManager assembler, +      final Computation lambda_fun, +      final Address collection, +      final Type collection_type, +      final List<Computation> extra_params +   ) +   { +      /* TODO: Quicksort implementation in Wyrd. */ +      return null; +   } +} diff --git a/src/core/src/tonkadur/wyrd/v1/lang/instruction/AddEventInput.java b/src/core/src/tonkadur/wyrd/v1/lang/instruction/AddEventInput.java new file mode 100644 index 0000000..5d476a5 --- /dev/null +++ b/src/core/src/tonkadur/wyrd/v1/lang/instruction/AddEventInput.java @@ -0,0 +1,66 @@ +package tonkadur.wyrd.v1.lang.instruction; + +import java.util.List; + +import tonkadur.wyrd.v1.lang.meta.Computation; +import tonkadur.wyrd.v1.lang.meta.Instruction; +import tonkadur.wyrd.v1.lang.meta.InstructionVisitor; + +public class AddEventInput extends Instruction +{ +   /***************************************************************************/ +   /**** MEMBERS **************************************************************/ +   /***************************************************************************/ +   protected final String name; +   protected final List<Computation> parameters; + +   /***************************************************************************/ +   /**** PUBLIC ***************************************************************/ +   /***************************************************************************/ +   /**** Constructors *********************************************************/ +   public AddEventInput (final String name, final List<Computation> parameters) +   { +      this.name = name; +      this.parameters = parameters; +   } + +   /**** Accessors ************************************************************/ +   public String get_name () +   { +      return name; +   } + +   public List<Computation> get_parameters () +   { +      return parameters; +   } + +   @Override +   public void get_visited_by (final InstructionVisitor iv) +   throws Throwable +   { +      iv.visit_add_event_input(this); +   } + +   /**** Misc. ****************************************************************/ +   @Override +   public String toString () +   { +      final StringBuilder sb; + +      sb = new StringBuilder(); + +      sb.append("(AddEventInput "); +      sb.append(name); + +      for (final Computation param: parameters) +      { +         sb.append(" "); +         sb.append(param.toString()); +      } + +      sb.append(")"); + +      return sb.toString(); +   } +} diff --git a/src/core/src/tonkadur/wyrd/v1/lang/meta/InstructionVisitor.java b/src/core/src/tonkadur/wyrd/v1/lang/meta/InstructionVisitor.java index 72a4cd4..2d79298 100644 --- a/src/core/src/tonkadur/wyrd/v1/lang/meta/InstructionVisitor.java +++ b/src/core/src/tonkadur/wyrd/v1/lang/meta/InstructionVisitor.java @@ -7,6 +7,9 @@ public interface InstructionVisitor     public void visit_add_choice (final AddChoice n)     throws Throwable; +   public void visit_add_event_input (final AddEventInput n) +   throws Throwable; +     public void visit_assert (final Assert n)     throws Throwable; diff --git a/src/json-export/src/tonkadur/jsonexport/InstructionCompiler.java b/src/json-export/src/tonkadur/jsonexport/InstructionCompiler.java index 22c2fca..86b2a56 100644 --- a/src/json-export/src/tonkadur/jsonexport/InstructionCompiler.java +++ b/src/json-export/src/tonkadur/jsonexport/InstructionCompiler.java @@ -27,6 +27,31 @@ public class InstructionCompiler implements InstructionVisitor        result.put("label", label_cc.get_result());     } +   public void visit_add_event_input (final AddEventInput n) +   throws Throwable +   { +      final JSONArray params; + +      params = new JSONArray(); + +      for (final Computation c: n.get_parameters()) +      { +         final ComputationCompiler cc; + +         cc = new ComputationCompiler(); + +         c.get_visited_by(cc); + +         params.add(cc.get_result()); +      } + +      result = new JSONObject(); + +      result.put("category", "add_event_input"); +      result.put("event", n.get_name()); +      result.put("parameters", params); +   } +     public void visit_assert (final Assert n)     throws Throwable     { | 


