summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/tests/player_choices.fate98
-rw-r--r--src/core/src/tonkadur/fate/v1/parser/FateLexer.g44
-rw-r--r--src/core/src/tonkadur/fate/v1/parser/FateParser.g4101
-rw-r--r--src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/InstructionCompiler.java93
-rw-r--r--src/core/src/tonkadur/wyrd/v1/compiler/util/registers/RegisterContext.java1
-rw-r--r--src/core/src/tonkadur/wyrd/v1/compiler/util/registers/RegisterManager.java8
-rw-r--r--src/core/src/tonkadur/wyrd/v1/lang/computation/GetLastChoiceIndex.java37
-rw-r--r--src/core/src/tonkadur/wyrd/v1/lang/meta/ComputationVisitor.java3
-rw-r--r--src/json-export/src/tonkadur/jsonexport/ComputationCompiler.java8
9 files changed, 343 insertions, 10 deletions
diff --git a/data/tests/player_choices.fate b/data/tests/player_choices.fate
new file mode 100644
index 0000000..2148863
--- /dev/null
+++ b/data/tests/player_choices.fate
@@ -0,0 +1,98 @@
+(fate_version 1)
+
+(global int i)
+
+(player_choice
+ (
+ ( Wrong Choice 0 )
+ (set i 1)
+ (assert (false) FAILED: Player Choice A)
+ )
+ (
+ ( Right Choice )
+ Took the right choice.
+ (set i 2)
+ )
+ (
+ ( Wrong Choice 1 )
+ (set i 1)
+ (assert (false) FAILED: Player Choice B)
+ )
+)
+
+(assert (= (var i) 2) FAILED: Player Choice C, i: (var i))
+
+(player_choice
+ (if (false)
+ (
+ ( Wrong Choice 0 )
+ (set i 1)
+ )
+ )
+ (ifelse (false)
+ (
+ ( Wrong Choice 1 )
+ (set i 3)
+ )
+ (if (true)
+ (
+ ( Right Choice )
+ (set i 6)
+ )
+ )
+ )
+)
+
+(assert (= (var i) 6) FAILED: Player Choice D, i: (var i))
+
+(global (set int) test_set)
+
+(while (>= (var i) 0)
+ (add (var i) test_set)
+ (set i (- (var i) 1))
+)
+
+(foreach test_set e
+ (var e)
+)
+
+(player_choice
+ (if (false)
+ (
+ ( Wrong Choice -1 )
+ (set i 1)
+ )
+ )
+ (foreach test_set e
+ (ifelse (= (var e) 3)
+ (
+ ( Correct Choice (var e) )
+ (
+ Chosen var e: (var e)
+ (set i 653)
+ )
+ )
+ (
+ ( Wrong Choice (var e) )
+ (
+ Chosen var e: (var e)
+ (set i (var e))
+ )
+ )
+ )
+ )
+ (ifelse (false)
+ (
+ ( Wrong Choice 1 )
+ (set i 3)
+ )
+ (
+ ( Wrong Choice Other )
+ (set i 6)
+ )
+ )
+)
+
+(assert (= (var i) 653) FAILED: Player Choice E, i: (var i))
+
+(end)
diff --git a/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 b/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4
index 7077127..1525d42 100644
--- a/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4
+++ b/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4
@@ -82,10 +82,9 @@ REF_KW: L_PAREN (((('ref'('erence'?))|'ptr'|'pointer')(US'to')?)|('address'(US'o
REMOVE_ALL_KW: L_PAREN 'remove'US'all' SEP+;
REVERSE_KW: L_PAREN 'reverse'(US'list')? SEP+;
REMOVE_ONE_KW: L_PAREN 'remove'US'one' SEP+;
-REMOVE_AT_KW: L_PAREN ('remove'US('elem'('ent')?US)?'at'|'rm'|'del'|'delete') SEP+;
+REMOVE_AT_KW: L_PAREN ('remove'US('elem'('ent')?US)?'at') SEP+;
REQUIRE_EXTENSION_KW: L_PAREN 'require'US'extension' SEP+;
REQUIRE_KW: L_PAREN 'require' SEP+;
-SEQUENCE_KW: L_PAREN 'seq'('uence')? SEP+;
SET_FIELDS_KW: L_PAREN 'set'US'fields' SEP+;
SET_KW: L_PAREN 'set'(US(('val''ue'?)|('var''iable'?)))? SEP+;
LIST_KW: L_PAREN 'list' SEP+;
@@ -94,7 +93,6 @@ SWITCH_KW: L_PAREN 'switch' SEP+;
TIMES_KW: L_PAREN ('times'|'*') SEP+;
TRUE_KW: L_PAREN 'true)';
DONE_KW: L_PAREN 'done)';
-VAL_KW: L_PAREN ('val'|'value') SEP+;
VARIABLE_KW: L_PAREN ('variable'|'var') SEP+;
VISIT_KW: L_PAREN ('call'|'visit')(US(('seq'('uence'?))|('proc'('edure'?))))? SEP+;
CONTINUE_AS_KW: L_PAREN (('continue'US('as'|'to'|'with'))|('jump'(US'to')?)|('go'US'to')|'exec')(US(('seq'('uence'?))|('proc'('edure'?))))? SEP+;
diff --git a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
index f122a9a..2c6aeca 100644
--- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
+++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
@@ -1351,6 +1351,105 @@ returns [Instruction result]
($player_choice.result)
);
}
+
+ | FOR_EACH_KW
+ value_reference WS+ new_reference_name
+ {
+ final Map<String, Variable> variable_map;
+ final Variable new_variable;
+ final Type collection_type;
+ Type elem_type;
+
+ elem_type = Type.ANY;
+
+ collection_type = ($value_reference.result).get_type();
+
+ if (collection_type instanceof CollectionType)
+ {
+ elem_type = ((CollectionType) collection_type).get_content_type();
+ }
+ else
+ {
+ ErrorManager.handle
+ (
+ new InvalidTypeException
+ (
+ CONTEXT.get_origin_at
+ (
+ ($FOR_EACH_KW.getLine()),
+ ($FOR_EACH_KW.getCharPositionInLine())
+ ),
+ elem_type,
+ Type.COLLECTION_TYPES
+ )
+ );
+
+ elem_type = Type.ANY;
+ }
+
+
+ new_variable =
+ new Variable
+ (
+ CONTEXT.get_origin_at
+ (
+ ($FOR_EACH_KW.getLine()),
+ ($FOR_EACH_KW.getCharPositionInLine())
+ ),
+ elem_type,
+ ($new_reference_name.result)
+ );
+
+ variable_map = LOCAL_VARIABLES.peekFirst();
+
+ if (variable_map.containsKey(($new_reference_name.result)))
+ {
+ ErrorManager.handle
+ (
+ new DuplicateLocalVariableException
+ (
+ variable_map.get(($new_reference_name.result)),
+ new_variable
+ )
+ );
+ }
+ else
+ {
+ variable_map.put(($new_reference_name.result), new_variable);
+ }
+ }
+ WS+
+ {
+ BREAKABLE_LEVELS++;
+ HIERARCHICAL_VARIABLES.push(new ArrayList());
+ }
+ player_choice_list
+ {
+ BREAKABLE_LEVELS--;
+
+ for (final String s: HIERARCHICAL_VARIABLES.pop())
+ {
+ LOCAL_VARIABLES.peekFirst().remove(s);
+ }
+ }
+ WS*
+ R_PAREN
+ {
+ $result =
+ new ForEach
+ (
+ CONTEXT.get_origin_at
+ (
+ ($FOR_EACH_KW.getLine()),
+ ($FOR_EACH_KW.getCharPositionInLine())
+ ),
+ ($value_reference.result),
+ ($new_reference_name.result),
+ ($player_choice_list.result)
+ );
+
+ variable_map.remove(($new_reference_name.result));
+ }
;
catch [final Throwable e]
{
@@ -2757,7 +2856,7 @@ returns [Reference result]
);
}
- | FIELD_KW value_reference WORD R_PAREN
+ | FIELD_KW value_reference WS+ WORD WS* R_PAREN
{
$result =
FieldReference.build
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 2c163e7..42df895 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
@@ -24,6 +24,7 @@ import tonkadur.wyrd.v1.lang.computation.Operation;
import tonkadur.wyrd.v1.lang.computation.Address;
import tonkadur.wyrd.v1.lang.computation.RelativeAddress;
import tonkadur.wyrd.v1.lang.computation.Size;
+import tonkadur.wyrd.v1.lang.computation.GetLastChoiceIndex;
import tonkadur.wyrd.v1.lang.computation.ValueOf;
import tonkadur.wyrd.v1.lang.instruction.AddChoice;
@@ -1291,9 +1292,12 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor
*
* Wyrd (add_choice label i0)
*/
+ final List<Instruction> to_next, labels_only;
final ComputationCompiler cc;
final String start_of_effect, end_of_effect;
+ to_next = new ArrayList<Instruction>();
+ labels_only = new ArrayList<Instruction>();
cc = new ComputationCompiler(compiler);
start_of_effect = compiler.assembler().generate_label("<choice#start>");
@@ -1306,7 +1310,7 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor
result.add(cc.get_init());
}
- result.add
+ labels_only.add
(
new AddChoice
(
@@ -1314,13 +1318,62 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor
compiler.assembler().get_label_constant(start_of_effect)
)
);
+
+ 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
(
- new SetPC
+ If.generate
(
- compiler.assembler().get_label_constant(end_of_effect)
+ 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
)
@@ -1359,13 +1412,29 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor
)
throws Throwable
{
- final String end_of_choices_label;
+ final String start_of_choices_label, end_of_choices_label;
+
+ start_of_choices_label =
+ compiler.assembler().generate_label("<ChoicesDefinition>");
end_of_choices_label =
compiler.assembler().generate_label("<ChoicesResolved>");
compiler.assembler().push_context_label("choices", end_of_choices_label);
+ result.add
+ (
+ compiler.assembler().mark_after
+ (
+ new SetValue
+ (
+ compiler.registers().get_choice_number_holder().get_address(),
+ new Constant(Type.INT, "-2")
+ ),
+ start_of_choices_label
+ )
+ );
+
/*
* Fate: (player_choice_list i0 ... in)
*
@@ -1386,11 +1455,25 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor
compiler.assembler().pop_context_label("choices");
+ result.add(new ResolveChoices());
+
+ result.add
+ (
+ new SetValue
+ (
+ compiler.registers().get_choice_number_holder().get_address(),
+ new Constant(Type.INT, "0")
+ )
+ );
+
result.add
(
compiler.assembler().mark_after
(
- new ResolveChoices(),
+ new SetPC
+ (
+ compiler.assembler().get_label_constant(start_of_choices_label)
+ ),
end_of_choices_label
)
);
diff --git a/src/core/src/tonkadur/wyrd/v1/compiler/util/registers/RegisterContext.java b/src/core/src/tonkadur/wyrd/v1/compiler/util/registers/RegisterContext.java
index 08c71f2..090f596 100644
--- a/src/core/src/tonkadur/wyrd/v1/compiler/util/registers/RegisterContext.java
+++ b/src/core/src/tonkadur/wyrd/v1/compiler/util/registers/RegisterContext.java
@@ -146,6 +146,7 @@ class RegisterContext
public void unbind (final String name)
{
+ release(aliased_registers.get(name));
aliased_registers.remove(name);
}
diff --git a/src/core/src/tonkadur/wyrd/v1/compiler/util/registers/RegisterManager.java b/src/core/src/tonkadur/wyrd/v1/compiler/util/registers/RegisterManager.java
index 2fbad42..8af7754 100644
--- a/src/core/src/tonkadur/wyrd/v1/compiler/util/registers/RegisterManager.java
+++ b/src/core/src/tonkadur/wyrd/v1/compiler/util/registers/RegisterManager.java
@@ -37,7 +37,7 @@ public class RegisterManager
protected final Map<String, StackableRegisterContext> context_by_name;
protected final Deque<RegisterContext> context;
protected final RegisterContext base_context, parameter_context;
- protected final Register next_pc, pc_stack;
+ protected final Register next_pc, pc_stack, choice_number;
protected int created_contexts;
public RegisterManager ()
@@ -45,6 +45,7 @@ public class RegisterManager
base_context = new RegisterContext("base context");
parameter_context = new RegisterContext("parameter context", ".param.");
next_pc = base_context.reserve(Type.INT);
+ choice_number = base_context.reserve(Type.INT);
pc_stack = base_context.reserve(new MapType(Type.INT));
context_by_name = new HashMap<String, StackableRegisterContext>();
@@ -69,6 +70,11 @@ public class RegisterManager
return context_name_prefix + (created_contexts++);
}
+ public Register get_choice_number_holder ()
+ {
+ return choice_number;
+ }
+
public void create_stackable_context (final String context_name)
{
final StackableRegisterContext result;
diff --git a/src/core/src/tonkadur/wyrd/v1/lang/computation/GetLastChoiceIndex.java b/src/core/src/tonkadur/wyrd/v1/lang/computation/GetLastChoiceIndex.java
new file mode 100644
index 0000000..8f70687
--- /dev/null
+++ b/src/core/src/tonkadur/wyrd/v1/lang/computation/GetLastChoiceIndex.java
@@ -0,0 +1,37 @@
+package tonkadur.wyrd.v1.lang.computation;
+
+import tonkadur.wyrd.v1.lang.type.Type;
+
+import tonkadur.wyrd.v1.lang.meta.Computation;
+import tonkadur.wyrd.v1.lang.meta.ComputationVisitor;
+
+public class GetLastChoiceIndex extends Computation
+{
+ /***************************************************************************/
+ /**** MEMBERS **************************************************************/
+ /***************************************************************************/
+
+ /***************************************************************************/
+ /**** PUBLIC ***************************************************************/
+ /***************************************************************************/
+ /**** Constructors *********************************************************/
+ public GetLastChoiceIndex ()
+ {
+ super(Type.INT);
+ }
+
+ /**** Accessors ************************************************************/
+ @Override
+ public void get_visited_by (final ComputationVisitor cv)
+ throws Throwable
+ {
+ cv.visit_get_last_choice_index(this);
+ }
+
+ /**** Misc. ****************************************************************/
+ @Override
+ public String toString ()
+ {
+ return "(GetLastChoiceIndex)";
+ }
+}
diff --git a/src/core/src/tonkadur/wyrd/v1/lang/meta/ComputationVisitor.java b/src/core/src/tonkadur/wyrd/v1/lang/meta/ComputationVisitor.java
index fdfdc1b..1d9b2be 100644
--- a/src/core/src/tonkadur/wyrd/v1/lang/meta/ComputationVisitor.java
+++ b/src/core/src/tonkadur/wyrd/v1/lang/meta/ComputationVisitor.java
@@ -31,6 +31,9 @@ public interface ComputationVisitor
public void visit_relative_address (final RelativeAddress n)
throws Throwable;
+ public void visit_get_last_choice_index (final GetLastChoiceIndex n)
+ throws Throwable;
+
public void visit_rich_text (final RichText n)
throws Throwable;
diff --git a/src/json-export/src/tonkadur/jsonexport/ComputationCompiler.java b/src/json-export/src/tonkadur/jsonexport/ComputationCompiler.java
index 3210f73..132e658 100644
--- a/src/json-export/src/tonkadur/jsonexport/ComputationCompiler.java
+++ b/src/json-export/src/tonkadur/jsonexport/ComputationCompiler.java
@@ -116,6 +116,14 @@ public class ComputationCompiler implements ComputationVisitor
result.put("category", "newline");
}
+ public void visit_get_last_choice_index (final GetLastChoiceIndex n)
+ throws Throwable
+ {
+ result = new JSONObject();
+
+ result.put("category", "last_choice_index");
+ }
+
public void visit_operation (final Operation n)
throws Throwable
{