summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/examples/blackjack/main.fate4
-rw-r--r--data/examples/blackjack/play.fate14
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/InputEvent.java181
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/World.java15
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/instruction/PlayerChoice.java30
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/instruction/PlayerInput.java134
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/instruction/PlayerOption.java (renamed from src/core/src/tonkadur/fate/v1/lang/instruction/PlayerChoiceList.java)37
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/meta/InstructionVisitor.java5
-rw-r--r--src/core/src/tonkadur/fate/v1/parser/FateLexer.g43
-rw-r--r--src/core/src/tonkadur/fate/v1/parser/FateParser.g4129
-rw-r--r--src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/ComputationCompiler.java6
-rw-r--r--src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/InstructionCompiler.java174
-rw-r--r--src/core/src/tonkadur/wyrd/v1/compiler/util/BinarySearch.java203
-rw-r--r--src/core/src/tonkadur/wyrd/v1/compiler/util/PopElement.java11
-rw-r--r--src/core/src/tonkadur/wyrd/v1/compiler/util/Sort.java46
-rw-r--r--src/core/src/tonkadur/wyrd/v1/lang/instruction/AddEventInput.java66
-rw-r--r--src/core/src/tonkadur/wyrd/v1/lang/meta/InstructionVisitor.java3
-rw-r--r--src/json-export/src/tonkadur/jsonexport/InstructionCompiler.java25
18 files changed, 1028 insertions, 58 deletions
diff --git a/data/examples/blackjack/main.fate b/data/examples/blackjack/main.fate
index acfee7e..342a663 100644
--- a/data/examples/blackjack/main.fate
+++ b/data/examples/blackjack/main.fate
@@ -24,7 +24,7 @@ Just between you and me, someone left those laying around, they aren't mine.
Now, you're all set to go... unless you don't know how to play?
(player_choice
- (
+ (option
( As it happens, I do not. )
(visit rules_of_blackjack)
(text_effect action_description
@@ -32,7 +32,7 @@ Now, you're all set to go... unless you don't know how to play?
)
(visit play_a_game)
)
- (
+ (option
( I am familiar with BlackJack. )
(text_effect action_description
You leave the counter and approach one of the tables.
diff --git a/data/examples/blackjack/play.fate b/data/examples/blackjack/play.fate
index 2cf2407..81c7c58 100644
--- a/data/examples/blackjack/play.fate
+++ b/data/examples/blackjack/play.fate
@@ -83,13 +83,13 @@
Interesting. Would you like to go again?
(player_choice
- (
+ (option
( Yes, please. )
Very well.
(newline)
(jump_to play_a_game)
)
- (
+ (option
( No, thank you. )
It was a pleasure to play with you. Farewell.
(newline)
@@ -153,17 +153,17 @@
)
(player_choice
- (
+ (option
( Another card, please. )
(set has_doubled (false))
(jump_to acquire_card)
)
- (
+ (option
( I will stand. )
(jump_to resolve_dealer)
)
(if (and (>= player_score 9) (<= player_score 11))
- (
+ (option
( Double my bet, I'll only take one card. )
(set bet (* bet 2))
(set has_doubled (true))
@@ -215,11 +215,11 @@
)
(player_choice
- (
+ (option
( Another card, please. )
(jump_to acquire_card)
)
- (
+ (option
( This will do. I stand. )
(jump_to resolve_dealer)
)
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
{