summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/examples/blackjack/cards.fate116
-rw-r--r--data/examples/blackjack/global.fate36
-rw-r--r--data/examples/blackjack/main.fate77
-rw-r--r--data/examples/blackjack/play.fate293
-rw-r--r--data/examples/blackjack/player.fate9
-rw-r--r--data/examples/blackjack/rules.fate5
-rw-r--r--data/tests/user_inputs.fate14
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/World.java1
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/computation/IsEmpty.java97
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/computation/ValueToRichText.java6
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/instruction/AddElementAt.java199
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/instruction/AddElementsOf.java170
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/meta/ComputationVisitor.java3
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/meta/InstructionVisitor.java6
-rw-r--r--src/core/src/tonkadur/fate/v1/parser/FateLexer.g45
-rw-r--r--src/core/src/tonkadur/fate/v1/parser/FateParser.g445
-rw-r--r--src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/ComputationCompiler.java19
-rw-r--r--src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/InstructionCompiler.java123
-rw-r--r--src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/TypeCompiler.java28
19 files changed, 1223 insertions, 29 deletions
diff --git a/data/examples/blackjack/cards.fate b/data/examples/blackjack/cards.fate
new file mode 100644
index 0000000..2312f03
--- /dev/null
+++ b/data/examples/blackjack/cards.fate
@@ -0,0 +1,116 @@
+(fate_version 1)
+
+(declare_structure card
+ ( text name )
+ ( int number )
+ ( int score )
+)
+
+(local (list card) heart_cards)
+(local (list card) spade_cards)
+(local (list card) club_cards)
+(local (list card) diamond_cards)
+
+(define_sequence generate_card_familly ((string name) ((ptr (list card)) deck))
+ (local int i)
+
+ (for (set i 1) (=< (var i) 13) (set i (+ (var i) 1))
+ (local card c)
+
+ (set c.number (var i))
+
+ (set c.name
+ (text
+ (switch (var i)
+ (1 Ace)
+ (11 Jack)
+ (12 Queen)
+ (13 Kind)
+ (cast string (var i))
+ )
+ of (var name)
+ )
+ )
+
+ (set c.score
+ (switch (var i)
+ (11 10)
+ (12 10)
+ (13 10)
+ (var i)
+ )
+ )
+
+ (add (var c) (at deck))
+ )
+)
+
+(visit generate_card_familly Hearts (ptr heart_cards))
+(visit generate_card_familly Spades (ptr spade_cards))
+(visit generate_card_familly Diamonds (ptr diamond_cards))
+(visit generate_card_familly Clubs (ptr club_cards))
+
+(global (list card) deck_template)
+
+(add_all heart_cards deck_template)
+(add_all spade_cards deck_template)
+(add_all diamond_cards deck_template)
+(add_all club_cards deck_template)
+
+(define_sequence shuffle_into_deck
+ (
+ ((ptr (list card)) cards)
+ ((ptr (list card)) deck)
+ )
+
+ (while (! (is_empty (at cards)))
+ (local int o)
+ (local int d)
+
+ (set o (rand 0 (- (size (at cards)) 1)))
+
+ (if_else (is_empty (at deck))
+ (set d 0)
+ (set d (rand 0 (- (size (at deck)) 1)))
+ )
+
+ (add_at (var d) (access (at cards) (var o)) (at deck))
+ (remove_at (var o) (at cards))
+ )
+)
+
+(define_sequence generate_shuffled_deck (((ptr (list card)) result))
+ (local (list card) initial_deck)
+
+ (set initial_deck (var deck_template))
+
+ (clear (at result))
+ (visit shuffle_into_deck (ptr initial_deck) (var result))
+)
+
+(define_sequence draw_a_card (((ptr (list card)) deck) ((ptr card) result))
+ (set (at result) (access (at deck) 0))
+ (remove_at 0 (at deck))
+)
+
+(define_sequence compute_score (((ptr (list card)) deck) ((ptr int) result))
+ (local int aces_count)
+ (local int maybe_better_score)
+
+ (set (at result) 0)
+
+ (foreach (at deck) card
+ (set (at result) (+ (var card.score) (at result)))
+ (if (= (var card.number) 1)
+ (set aces_count (+ (var aces_count) 1))
+ )
+ )
+
+ (while (> (var aces_count) 0)
+ (set maybe_better_score (+ (at result) 10))
+ (if (=< (var maybe_better_score) 21)
+ (set (at result) (var maybe_better_score))
+ )
+ (set aces_count (- (var aces_count) 1))
+ )
+)
diff --git a/data/examples/blackjack/global.fate b/data/examples/blackjack/global.fate
new file mode 100644
index 0000000..9c10c9f
--- /dev/null
+++ b/data/examples/blackjack/global.fate
@@ -0,0 +1,36 @@
+(fate_version 1)
+
+(require player.fate)
+
+(global player player)
+
+(global (lambda text (int)) coins_word)
+
+(set coins_word
+ (lambda ((int i))
+ (if_else (= (var i) 1)
+ (text a single coin )
+ (text (var i) coins )
+ )
+ )
+)
+
+(declare_text_effect action_description)
+
+(define_sequence money_acquisition ((int amount))
+ (set player.money (+ (var player.money) (var amount)))
+ (if (> (var amount) 0)
+ (text_effect action_description
+ You acquired (eval coins_word (var amount))!
+ )
+ )
+)
+
+(define_sequence money_loss ((int amount))
+ (set player.money (- (var player.money) (var amount)))
+ (if (> (var amount) 0)
+ (text_effect action_description
+ You lost (eval coins_word (var amount)).
+ )
+ )
+)
diff --git a/data/examples/blackjack/main.fate b/data/examples/blackjack/main.fate
new file mode 100644
index 0000000..0b5acf8
--- /dev/null
+++ b/data/examples/blackjack/main.fate
@@ -0,0 +1,77 @@
+(fate_version 1)
+
+(require player.fate)
+(require global.fate)
+(require cards.fate)
+(require rules.fate)
+(require play.fate)
+
+(local int original_amount)
+
+(set player.money 0)
+
+Welcome to Tonkadur's wonderful and totally original blackjack!
+Say, I don't think I've seen you before...
+No, no, I am sure I haven't, actually.
+(prompt_string player.name 1 64 What's your name, then?)
+Alright, (var player.name), well, since it's your first time here, let me give
+you some coins.
+Just between you and me, someone left those laying around, they aren't mine.
+
+(visit money_acquisition (+ 100 (rand 0 100)))
+(set original_amount (var player.money))
+
+Now, you're all set to go... unless you don't know how to play?
+
+(player_choice
+ (
+ ( As it happens, I do not. )
+ (visit rules_of_blackjack)
+ (text_effect action_description
+ You leave the counter and approach one of the tables.
+ )
+ (visit play_a_game)
+ )
+ (
+ ( I am familiar with BlackJack. )
+ (text_effect action_description
+ You leave the counter and approach one of the tables.
+ )
+ (visit play_a_game)
+ )
+)
+(text_effect action_description
+ As you leave the establishment, the receptionist notices you.
+)
+
+(cond
+ (
+ (=< (var player.money) (/ (var original_amount) 2))
+ Outch. I suppose all your luck was spent by getting these free coins.
+ )
+ (
+ (< (var player.money) (var original_amount))
+ Well, that's not too bad for your first time. Come back tomorrow, I am
+ sure you'll be getting it all back.
+ )
+ (
+ (< (var player.money) (* (var original_amount) 2))
+ Had a good day, I hope?
+ )
+ (
+ (< (var player.money) (* (var original_amount) 4))
+ Well! That was some fine play, if I do say so myself!
+ )
+ (
+ (true)
+ (var player.name)! How did you do that?! You have to teach me! I did give
+ you the tools of your success, so please?
+ )
+)
+
+(text_effect action_description
+ You walk out, having turned (eval coins_word (var original_amount)) into
+ (eval coins_word (var player.money)).
+)
+
+(end)
diff --git a/data/examples/blackjack/play.fate b/data/examples/blackjack/play.fate
new file mode 100644
index 0000000..4c2913f
--- /dev/null
+++ b/data/examples/blackjack/play.fate
@@ -0,0 +1,293 @@
+(fate_version 1)
+
+(require player.fate)
+(require global.fate)
+(require cards.fate)
+
+(global bool has_played)
+(global (list card) current_deck)
+(global (list card) dealer_hand)
+(global int bet)
+(global bool has_doubled)
+
+(set has_played (false))
+
+(define_sequence play_a_game ()
+ (local card new_card)
+
+ (if (not (var has_played))
+ (text_effect action_description
+ Sitting yourself at a table, you see someone rushing to set up the
+ cards and manage the game.
+ )
+ )
+ (if (= (var player.money) 0)
+ (
+ I am sorry, (var player.name), but you appear to have ran out of coins.
+ (done)
+ )
+ )
+ (prompt_integer bet 1 (var player.money) How much would you like to bet?)
+ (text_effect action_description
+ The dealer shuffles the cards and starts dealing.
+ )
+
+ (newline)
+
+ (visit generate_shuffled_deck (ptr current_deck))
+
+ (visit draw_a_card (ptr current_deck) (ptr new_card))
+ (add (var new_card) player.hand)
+
+ (text_effect action_description
+ You have been dealt the (var new_card.name).
+ (newline)
+ )
+
+
+ (visit draw_a_card (ptr current_deck) (ptr new_card))
+ (add (var new_card) dealer_hand)
+
+ (text_effect action_description
+ The dealer has drawn the (var new_card.name).
+ (newline)
+ )
+
+ (visit draw_a_card (ptr current_deck) (ptr new_card))
+ (add (var new_card) player.hand)
+
+ (text_effect action_description
+ You have been dealt the (var new_card.name).
+ (newline)
+ )
+
+ (newline)
+
+ (visit draw_a_card (ptr current_deck) (ptr new_card))
+ (add (var new_card) dealer_hand)
+
+ (text_effect action_description
+ The dealer has drawn a card, face down.
+ (newline)
+ )
+
+ (visit initial_draw)
+
+ (clear dealer_hand)
+
+ (newline)
+ Interesting. Would you like to go again?
+
+ (player_choice
+ (
+ ( Yes, please. )
+ Very well.
+ (newline)
+ (jump_to play_a_game)
+ )
+ (
+ ( No, thank you. )
+ It was a pleasure to play with you. Farewell.
+ (newline)
+ (done)
+ )
+ )
+)
+
+(define_sequence initial_draw ()
+ (local int dealer_score)
+ (local int player_score)
+
+ (visit compute_score (ptr dealer_hand) (ptr dealer_score))
+ (visit compute_score (ptr player.hand) (ptr player_score))
+
+ (if (= (var dealer_score) 21)
+ (ifelse (= (var player_score) 21)
+ (
+ (text_effect action_description
+ The dealer looks very surprised.
+ )
+ (newline)
+ Double Blackjack! A tie, then.
+ (done)
+ )
+ (
+ (text_effect action_description
+ The dealer looks surprised, but happy.
+ )
+ (newline)
+ Blackjack! Looks like I win, this time.
+ (visit money_loss (var bet))
+ (done)
+ )
+ )
+ )
+
+ (if (= (var player_score) 21)
+ (
+ (text_effect action_description
+ The dealer looks surprised.
+ )
+ (newline)
+ Blackjack! Looks like you win, this time.
+ (newline)
+ (visit money_acquisition (cast int (* (cast float (var bet)) 1.5)))
+ (done)
+ )
+ )
+
+ (player_choice
+ (
+ ( Another card, please. )
+ (set has_doubled (false))
+ (jump_to acquire_card)
+ )
+ (
+ ( I will stand. )
+ (jump_to resolve_dealer)
+ )
+ (if (and (>= (var player_score) 9) (<= (var player_score) 11))
+ (
+ ( Double my bet, I'll only take one card. )
+ (set bet (* (var bet) 2))
+ (set has_doubled (true))
+ (jump_to acquire_card)
+ )
+ )
+ )
+)
+
+(define_sequence acquire_card ()
+ (local card new_card)
+ (local int player_score)
+
+ (visit draw_a_card (ptr current_deck) (ptr new_card))
+ (add (var new_card) player.hand)
+
+ (visit compute_score (ptr player.hand) (ptr player_score))
+
+ (text_effect action_description
+ You have been dealt the (var new_card.name).
+ (newline)
+ Your hand is currently:
+ )
+ (foreach player.hand card
+ (text_effect action_description
+ (newline)
+ * The (var card.name), worth
+ (if_else (= (var card.number) 1)
+ (text 1 or 11 points. )
+ (text (var card.score) points. )
+ )
+ )
+ )
+ (newline)
+
+ (if (> (var player_score) 21)
+ (
+ (text_effect action_description
+ The dealer looks disappointed.
+ )
+ (newline)
+ A bust! What a shame...
+ (newline)
+ (visit money_loss (var bet))
+ (done)
+ )
+ )
+
+ (if (var has_doubled)
+ (jump_to resolve_dealer)
+ )
+
+ (player_choice
+ (
+ ( Another card, please. )
+ (jump_to acquire_card)
+ )
+ (
+ ( This will do. I stand. )
+ (jump_to resolve_dealer)
+ )
+ )
+)
+
+(define_sequence resolve_dealer ()
+ (local int dealer_score)
+ (local int player_score)
+ (visit compute_score (ptr dealer_hand) (ptr dealer_score))
+
+ Very well. I shall now play my turn.
+ (newline)
+
+ (text_effect action_description
+ My current hand is:
+ (newline)
+ )
+ (foreach dealer_hand card
+ (text_effect action_description
+ (newline)
+ * The (var card.name), worth
+ (if_else (= (var card.number) 1)
+ (text 1 or 11 points. )
+ (text (var card.score) points. )
+ )
+ )
+ )
+ (newline)
+
+ (while (< (var dealer_score) 17)
+ (local card new_card)
+
+ (visit draw_a_card (ptr current_deck) (ptr new_card))
+ (add (var new_card) dealer_hand)
+
+ (text_effect action_description
+ The dealer has drawn the (var new_card.name).
+ (newline)
+ )
+
+ (visit compute_score (ptr dealer_hand) (ptr dealer_score))
+ )
+
+ (if (> (var dealer_score) 21)
+ (
+ (text_effect action_description
+ The dealer looks disappointed.
+ )
+ (newline)
+ Ah. It would appear I have gone above the limit.
+ (newline)
+ (visit money_acquisition (var bet))
+ (done)
+ )
+ )
+
+ (visit compute_score (ptr player.hand) (ptr player_score))
+
+ (var player_score) for you, against (var dealer_score) for me.
+
+ (newline)
+
+ (if (= (var player_score) (var dealer_score))
+ (
+ A tie, then.
+ (done)
+ )
+ )
+
+ (if_else (> (var player_score) (var dealer_score))
+ (
+ Congratulation, you won.
+ (newline)
+ (visit money_acquisition (var bet))
+ (done)
+ )
+ (
+ It would appear I have won this game.
+ (newline)
+ (visit money_loss (var bet))
+ (done)
+ )
+ )
+)
diff --git a/data/examples/blackjack/player.fate b/data/examples/blackjack/player.fate
new file mode 100644
index 0000000..7d8b947
--- /dev/null
+++ b/data/examples/blackjack/player.fate
@@ -0,0 +1,9 @@
+(fate_version 1)
+
+(require cards.fate)
+
+(define_structure player
+ (string name)
+ (int money)
+ ((list card) hand)
+)
diff --git a/data/examples/blackjack/rules.fate b/data/examples/blackjack/rules.fate
new file mode 100644
index 0000000..3e4c378
--- /dev/null
+++ b/data/examples/blackjack/rules.fate
@@ -0,0 +1,5 @@
+(fate_version 1)
+
+(define_sequence rules_of_blackjack ()
+ TODO
+)
diff --git a/data/tests/user_inputs.fate b/data/tests/user_inputs.fate
new file mode 100644
index 0000000..d238c7f
--- /dev/null
+++ b/data/tests/user_inputs.fate
@@ -0,0 +1,14 @@
+(fate_version 1)
+
+(local int i)
+
+(prompt_integer i 0 100 How likely is this test to fail?)
+Did you say (var i)? That sounds
+(ifelse (=< (var i) 50) ( unreasable ) ( very reasonable indeed)).
+
+(local string name)
+(prompt_string name 0 64 Oh, and what's your name?)
+
+I see, (var name), you might be on to something there...
+
+(end)
diff --git a/src/core/src/tonkadur/fate/v1/lang/World.java b/src/core/src/tonkadur/fate/v1/lang/World.java
index 893b0e6..047f1d5 100644
--- a/src/core/src/tonkadur/fate/v1/lang/World.java
+++ b/src/core/src/tonkadur/fate/v1/lang/World.java
@@ -284,6 +284,7 @@ public class World
//type_collection.add(Type.LIST);
//type_collection.add(Type.SET);
type_collection.add(Type.STRING);
+ type_collection.add(Type.RICH_TEXT);
}
catch (final Throwable t)
{
diff --git a/src/core/src/tonkadur/fate/v1/lang/computation/IsEmpty.java b/src/core/src/tonkadur/fate/v1/lang/computation/IsEmpty.java
new file mode 100644
index 0000000..66d40f0
--- /dev/null
+++ b/src/core/src/tonkadur/fate/v1/lang/computation/IsEmpty.java
@@ -0,0 +1,97 @@
+package tonkadur.fate.v1.lang.computation;
+
+import tonkadur.error.ErrorManager;
+
+import tonkadur.parser.Origin;
+
+import tonkadur.fate.v1.error.InvalidTypeException;
+
+import tonkadur.fate.v1.lang.type.CollectionType;
+import tonkadur.fate.v1.lang.type.Type;
+
+import tonkadur.fate.v1.lang.meta.ComputationVisitor;
+import tonkadur.fate.v1.lang.meta.Computation;
+
+public class IsEmpty extends Computation
+{
+ /***************************************************************************/
+ /**** MEMBERS **************************************************************/
+ /***************************************************************************/
+ protected final Computation collection;
+
+ /***************************************************************************/
+ /**** PROTECTED ************************************************************/
+ /***************************************************************************/
+ /**** Constructors *********************************************************/
+ protected IsEmpty
+ (
+ final Origin origin,
+ final Computation collection
+ )
+ {
+ super(origin, Type.BOOL);
+
+ this.collection = collection;
+ }
+
+ /***************************************************************************/
+ /**** PUBLIC ***************************************************************/
+ /***************************************************************************/
+ /**** Constructors *********************************************************/
+ public static IsEmpty build
+ (
+ final Origin origin,
+ final Computation collection
+ )
+ throws InvalidTypeException
+ {
+
+ if (!(collection.get_type() instanceof CollectionType))
+ {
+ ErrorManager.handle
+ (
+ new InvalidTypeException
+ (
+ collection.get_origin(),
+ collection.get_type(),
+ Type.COLLECTION_TYPES
+ )
+ );
+ }
+
+ return new IsEmpty(origin, collection);
+ }
+
+ /**** Accessors ************************************************************/
+ @Override
+ public void get_visited_by (final ComputationVisitor cv)
+ throws Throwable
+ {
+ cv.visit_is_empty(this);
+ }
+
+ public Computation get_collection ()
+ {
+ return collection;
+ }
+
+ /**** Misc. ****************************************************************/
+ @Override
+ public String toString ()
+ {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append(origin.toString());
+ sb.append("(IsEmpty");
+ sb.append(System.lineSeparator());
+ sb.append(System.lineSeparator());
+
+ sb.append("collection:");
+ sb.append(System.lineSeparator());
+ sb.append(collection.toString());
+
+ sb.append(")");
+
+ return sb.toString();
+ }
+}
diff --git a/src/core/src/tonkadur/fate/v1/lang/computation/ValueToRichText.java b/src/core/src/tonkadur/fate/v1/lang/computation/ValueToRichText.java
index 43c8371..b21024b 100644
--- a/src/core/src/tonkadur/fate/v1/lang/computation/ValueToRichText.java
+++ b/src/core/src/tonkadur/fate/v1/lang/computation/ValueToRichText.java
@@ -42,7 +42,11 @@ public class ValueToRichText extends RichTextNode
value_base_type = value.get_type().get_base_type();
- if (value_base_type.equals(Type.STRING))
+ if
+ (
+ value_base_type.equals(Type.STRING)
+ || value_base_type.equals(Type.RICH_TEXT)
+ )
{
return new ValueToRichText(value);
}
diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/AddElementAt.java b/src/core/src/tonkadur/fate/v1/lang/instruction/AddElementAt.java
new file mode 100644
index 0000000..4cd192f
--- /dev/null
+++ b/src/core/src/tonkadur/fate/v1/lang/instruction/AddElementAt.java
@@ -0,0 +1,199 @@
+package tonkadur.fate.v1.lang.instruction;
+
+import java.util.Collections;
+
+import tonkadur.error.ErrorManager;
+
+import tonkadur.parser.Origin;
+
+import tonkadur.fate.v1.error.ConflictingTypeException;
+import tonkadur.fate.v1.error.IncomparableTypeException;
+import tonkadur.fate.v1.error.InvalidTypeException;
+
+import tonkadur.fate.v1.lang.type.CollectionType;
+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;
+
+public class AddElementAt extends Instruction
+{
+ /***************************************************************************/
+ /**** MEMBERS **************************************************************/
+ /***************************************************************************/
+ protected final Computation index;
+ protected final Computation element;
+ protected final Computation collection;
+
+ /***************************************************************************/
+ /**** PROTECTED ************************************************************/
+ /***************************************************************************/
+ /**** Constructors *********************************************************/
+ protected AddElementAt
+ (
+ final Origin origin,
+ final Computation index,
+ final Computation element,
+ final Computation collection
+ )
+ {
+ super(origin);
+
+ this.index = index;
+ this.collection = collection;
+ this.element = element;
+ }
+
+ /***************************************************************************/
+ /**** PUBLIC ***************************************************************/
+ /***************************************************************************/
+ /**** Constructors *********************************************************/
+ public static AddElementAt build
+ (
+ final Origin origin,
+ final Computation index,
+ final Computation element,
+ final Computation collection
+ )
+ throws
+ InvalidTypeException,
+ ConflictingTypeException,
+ IncomparableTypeException
+ {
+ final Type hint;
+ final Type collection_type;
+ final CollectionType collection_true_type;
+ final Type collection_element_type;
+
+ collection_type = collection.get_type();
+
+ if
+ (
+ (!(collection_type instanceof CollectionType))
+ || (((CollectionType) collection_type).is_set())
+ )
+ {
+ ErrorManager.handle
+ (
+ new InvalidTypeException
+ (
+ collection.get_origin(),
+ collection.get_type(),
+ Collections.singletonList(Type.LIST)
+ )
+ );
+ }
+
+ if (!index.get_type().can_be_used_as(Type.INT))
+ {
+ ErrorManager.handle
+ (
+ new InvalidTypeException
+ (
+ index.get_origin(),
+ index.get_type(),
+ Collections.singletonList(Type.INT)
+ )
+ );
+ }
+
+ collection_true_type = (CollectionType) collection_type;
+ collection_element_type = collection_true_type.get_content_type();
+
+ if
+ (
+ element.get_type().can_be_used_as(collection_element_type)
+ ||
+ (element.get_type().try_merging_with(collection_element_type) != null)
+ )
+ {
+ return new AddElementAt(origin, index, element, collection);
+ }
+
+ ErrorManager.handle
+ (
+ new ConflictingTypeException
+ (
+ element.get_origin(),
+ element.get_type(),
+ collection_element_type
+ )
+ );
+
+ hint =
+ (Type) element.get_type().generate_comparable_to
+ (
+ collection_element_type
+ );
+
+ if (hint.equals(Type.ANY))
+ {
+ ErrorManager.handle
+ (
+ new IncomparableTypeException
+ (
+ element.get_origin(),
+ element.get_type(),
+ collection_element_type
+ )
+ );
+ }
+
+ return new AddElementAt(origin, index, element, collection);
+ }
+
+ /**** Accessors ************************************************************/
+ @Override
+ public void get_visited_by (final InstructionVisitor iv)
+ throws Throwable
+ {
+ iv.visit_add_element_at(this);
+ }
+
+ public Computation get_collection ()
+ {
+ return collection;
+ }
+
+ public Computation get_index ()
+ {
+ return index;
+ }
+
+ public Computation get_element ()
+ {
+ return element;
+ }
+
+ /**** Misc. ****************************************************************/
+ @Override
+ public String toString ()
+ {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append("(AddElementAt");
+ sb.append(System.lineSeparator());
+ sb.append(System.lineSeparator());
+
+ sb.append("index:");
+ sb.append(System.lineSeparator());
+ sb.append(index.toString());
+ sb.append(System.lineSeparator());
+ sb.append(System.lineSeparator());
+
+ sb.append("element:");
+ sb.append(System.lineSeparator());
+ sb.append(element.toString());
+ sb.append(System.lineSeparator());
+ sb.append(System.lineSeparator());
+
+ sb.append("collection:");
+ sb.append(System.lineSeparator());
+ sb.append(collection.toString());
+
+ sb.append(")");
+
+ return sb.toString();
+ }
+}
diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/AddElementsOf.java b/src/core/src/tonkadur/fate/v1/lang/instruction/AddElementsOf.java
new file mode 100644
index 0000000..7409b2b
--- /dev/null
+++ b/src/core/src/tonkadur/fate/v1/lang/instruction/AddElementsOf.java
@@ -0,0 +1,170 @@
+package tonkadur.fate.v1.lang.instruction;
+
+import tonkadur.error.ErrorManager;
+
+import tonkadur.parser.Origin;
+
+import tonkadur.fate.v1.error.ConflictingTypeException;
+import tonkadur.fate.v1.error.IncomparableTypeException;
+import tonkadur.fate.v1.error.InvalidTypeException;
+
+import tonkadur.fate.v1.lang.type.CollectionType;
+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.Reference;
+
+public class AddElementsOf extends Instruction
+{
+ /***************************************************************************/
+ /**** MEMBERS **************************************************************/
+ /***************************************************************************/
+ protected final Reference other_collection;
+ protected final Reference collection;
+
+ /***************************************************************************/
+ /**** PROTECTED ************************************************************/
+ /***************************************************************************/
+ /**** Constructors *********************************************************/
+ protected AddElementsOf
+ (
+ final Origin origin,
+ final Reference other_collection,
+ final Reference collection
+ )
+ {
+ super(origin);
+
+ this.collection = collection;
+ this.other_collection = other_collection;
+ }
+
+ /***************************************************************************/
+ /**** PUBLIC ***************************************************************/
+ /***************************************************************************/
+ /**** Constructors *********************************************************/
+ public static AddElementsOf build
+ (
+ final Origin origin,
+ final Reference other_collection,
+ final Reference collection
+ )
+ throws
+ InvalidTypeException,
+ ConflictingTypeException,
+ IncomparableTypeException
+ {
+ final Type hint;
+ final Type collection_type, other_collection_type;
+
+ collection_type = collection.get_type();
+ other_collection_type = other_collection.get_type();
+
+ if (!(collection_type instanceof CollectionType))
+ {
+ ErrorManager.handle
+ (
+ new InvalidTypeException
+ (
+ collection.get_origin(),
+ collection_type,
+ Type.COLLECTION_TYPES
+ )
+ );
+ }
+
+ if (!(other_collection_type instanceof CollectionType))
+ {
+ ErrorManager.handle
+ (
+ new InvalidTypeException
+ (
+ other_collection.get_origin(),
+ other_collection_type,
+ Type.COLLECTION_TYPES
+ )
+ );
+ }
+
+ if (other_collection_type.can_be_used_as(collection_type))
+ {
+ return new AddElementsOf(origin, other_collection, collection);
+ }
+
+ ErrorManager.handle
+ (
+ new ConflictingTypeException
+ (
+ other_collection.get_origin(),
+ other_collection_type,
+ collection_type
+ )
+ );
+
+ hint =
+ (Type) other_collection.get_type().generate_comparable_to
+ (
+ collection_type
+ );
+
+ if (hint.equals(Type.ANY))
+ {
+ ErrorManager.handle
+ (
+ new IncomparableTypeException
+ (
+ other_collection.get_origin(),
+ other_collection_type,
+ collection_type
+ )
+ );
+ }
+
+ return new AddElementsOf(origin, other_collection, collection);
+ }
+
+ /**** Accessors ************************************************************/
+ @Override
+ public void get_visited_by (final InstructionVisitor iv)
+ throws Throwable
+ {
+ iv.visit_add_elements_of(this);
+ }
+
+ public Reference get_source_collection ()
+ {
+ return other_collection;
+ }
+
+ public Reference get_target_collection ()
+ {
+ return collection;
+ }
+
+ /**** Misc. ****************************************************************/
+ @Override
+ public String toString ()
+ {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append(origin.toString());
+ sb.append("(AddElementsOf");
+ sb.append(System.lineSeparator());
+ sb.append(System.lineSeparator());
+
+ sb.append("other_collection:");
+ sb.append(System.lineSeparator());
+ sb.append(other_collection.toString());
+ sb.append(System.lineSeparator());
+ sb.append(System.lineSeparator());
+
+ sb.append("collection:");
+ sb.append(System.lineSeparator());
+ sb.append(collection.toString());
+
+ sb.append(")");
+
+ return sb.toString();
+ }
+}
diff --git a/src/core/src/tonkadur/fate/v1/lang/meta/ComputationVisitor.java b/src/core/src/tonkadur/fate/v1/lang/meta/ComputationVisitor.java
index 09b9135..1cdbcf5 100644
--- a/src/core/src/tonkadur/fate/v1/lang/meta/ComputationVisitor.java
+++ b/src/core/src/tonkadur/fate/v1/lang/meta/ComputationVisitor.java
@@ -52,6 +52,9 @@ public interface ComputationVisitor
public void visit_let (final Let n)
throws Throwable;
+ public void visit_is_empty (final IsEmpty n)
+ throws Throwable;
+
public void visit_newline (final Newline n)
throws Throwable;
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 6e0da72..30acc7d 100644
--- a/src/core/src/tonkadur/fate/v1/lang/meta/InstructionVisitor.java
+++ b/src/core/src/tonkadur/fate/v1/lang/meta/InstructionVisitor.java
@@ -8,6 +8,12 @@ public interface InstructionVisitor
public void visit_add_element (final AddElement ae)
throws Throwable;
+ public void visit_add_element_at (final AddElementAt n)
+ throws Throwable;
+
+ public void visit_add_elements_of (final AddElementsOf n)
+ throws Throwable;
+
public void visit_assert (final Assert a)
throws Throwable;
diff --git a/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 b/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4
index 271a766..03014ac 100644
--- a/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4
+++ b/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4
@@ -17,6 +17,8 @@ R_PAREN: ')';
ABS_KW: L_PAREN 'abs'('olute'?) SEP+;
ACCESS_KW: L_PAREN 'access' SEP+;
ADD_KW: L_PAREN 'add'(US'element')? SEP+;
+ADD_AT_KW: L_PAREN 'add'(US'element')?US'at' SEP+;
+ADD_ALL_KW: L_PAREN 'add'US'all'(US'elements')? SEP+;
AND_KW: L_PAREN ('and'|'/\\') SEP+;
ASSERT_KW: L_PAREN 'assert' SEP+;
AT_KW: L_PAREN 'at' SEP+;
@@ -28,7 +30,7 @@ COUNT_KW: L_PAREN 'count' SEP+;
DECLARE_ALIAS_TYPE_KW:
L_PAREN ((('declare'|'define'|'def')US(('sub'|'alias')US)?'type')|'typedef') SEP+;
DECLARE_DICT_TYPE_KW: L_PAREN
-('declare'|'define'|'def')US('dict'|('struct''ure'?))(US'type')? SEP+;
+ ('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_TEXT_EFFECT_KW: L_PAREN ('declare'|'define'|'def')US'text'US'effect' SEP+;
DECLARE_VARIABLE_KW: L_PAREN 'global' SEP+;
@@ -58,6 +60,7 @@ IMPLIES_KW: L_PAREN ('implies'|'=>'|'->') SEP+;
INCLUDE_KW: L_PAREN 'include' SEP+;
INDEX_OF_KW: L_PAREN ('index'US'of') SEP+;
IS_MEMBER_KW: L_PAREN ('is'US'member'|'contains'|'has') SEP+;
+IS_EMPTY_KW: L_PAREN 'is'US'empty' SEP+;
LOWER_EQUAL_THAN_KW: L_PAREN ('lower'US'equal'US'than'|'=<'|'<='|'le') SEP+;
LOWER_THAN_KW: L_PAREN ('lower'US'than'|'<'|'lt') SEP+;
LET_KW: L_PAREN 'let' SEP+;
diff --git a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
index 4c0a7a0..4cf3f8f 100644
--- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
+++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
@@ -571,6 +571,37 @@ returns [Instruction result]
);
}
+ | ADD_AT_KW index=value WS+ element=value WS+ value_reference WS* R_PAREN
+ {
+ $result =
+ AddElementAt.build
+ (
+ CONTEXT.get_origin_at
+ (
+ ($ADD_AT_KW.getLine()),
+ ($ADD_AT_KW.getCharPositionInLine())
+ ),
+ ($index.result),
+ ($element.result),
+ ($value_reference.result)
+ );
+ }
+
+ | ADD_ALL_KW source=value_reference WS+ target=value_reference WS* R_PAREN
+ {
+ $result =
+ AddElementsOf.build
+ (
+ CONTEXT.get_origin_at
+ (
+ ($ADD_ALL_KW.getLine()),
+ ($ADD_ALL_KW.getCharPositionInLine())
+ ),
+ ($source.result),
+ ($target.result)
+ );
+ }
+
| END_KW
{
$result =
@@ -2247,6 +2278,20 @@ returns [Computation result]:
);
}
+ | IS_EMPTY_KW value_reference WS* R_PAREN
+ {
+ $result =
+ IsEmpty.build
+ (
+ CONTEXT.get_origin_at
+ (
+ ($IS_EMPTY_KW.getLine()),
+ ($IS_EMPTY_KW.getCharPositionInLine())
+ ),
+ ($value_reference.result)
+ );
+ }
+
| INDEX_OF_KW value WS+ value_reference WS* R_PAREN
{
$result =
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 f30d433..996a246 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
@@ -1229,6 +1229,25 @@ implements tonkadur.fate.v1.lang.meta.ComputationVisitor
}
@Override
+ public void visit_is_empty
+ (
+ final tonkadur.fate.v1.lang.computation.IsEmpty n
+ )
+ throws Throwable
+ {
+ final ComputationCompiler cc;
+
+ cc = new ComputationCompiler(compiler);
+
+ n.get_collection().get_visited_by(cc);
+
+ assimilate(cc);
+
+ result_as_computation =
+ Operation.equals(new Size(cc.get_address()), Constant.ZERO);
+ }
+
+ @Override
public void visit_index_of_operator
(
final tonkadur.fate.v1.lang.computation.IndexOfOperator n
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 deb0772..55ff4a2 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
@@ -23,6 +23,7 @@ import tonkadur.wyrd.v1.lang.computation.Constant;
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.IfElseComputation;
import tonkadur.wyrd.v1.lang.computation.Size;
import tonkadur.wyrd.v1.lang.computation.GetLastChoiceIndex;
import tonkadur.wyrd.v1.lang.computation.ValueOf;
@@ -248,6 +249,128 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor
}
@Override
+ public void visit_add_elements_of
+ (
+ final tonkadur.fate.v1.lang.instruction.AddElementsOf n
+ )
+ throws Throwable
+ {
+ final tonkadur.fate.v1.lang.meta.Instruction as_fate;
+
+
+ as_fate =
+ new tonkadur.fate.v1.lang.instruction.ForEach
+ (
+ n.get_origin(),
+ n.get_source_collection(),
+ ".secret var of doom",
+ Collections.singletonList
+ (
+ tonkadur.fate.v1.lang.instruction.AddElement.build
+ (
+ n.get_origin(),
+ new tonkadur.fate.v1.lang.computation.VariableReference
+ (
+ n.get_origin(),
+ new tonkadur.fate.v1.lang.Variable
+ (
+ n.get_origin(),
+ (
+ (tonkadur.fate.v1.lang.type.CollectionType)
+ n.get_source_collection().get_type()
+ ).get_content_type(),
+ ".secret var of doom"
+ )
+ ),
+ n.get_target_collection()
+ )
+ )
+ );
+
+ as_fate.get_visited_by(this);
+ }
+
+ @Override
+ public void visit_add_element_at
+ (
+ final tonkadur.fate.v1.lang.instruction.AddElementAt n
+ )
+ throws Throwable
+ {
+ final Address collection_as_address;
+ final ComputationCompiler index_compiler, element_compiler;
+ final ComputationCompiler collection_compiler;
+ final Register index_holder;
+
+ index_holder = compiler.registers().reserve(Type.INT);
+
+ index_compiler = new ComputationCompiler(compiler);
+
+ n.get_index().get_visited_by(index_compiler);
+
+ if (index_compiler.has_init())
+ {
+ result.add(index_compiler.get_init());
+ }
+
+
+ element_compiler = new ComputationCompiler(compiler);
+
+ n.get_element().get_visited_by(element_compiler);
+
+ if (element_compiler.has_init())
+ {
+ result.add(element_compiler.get_init());
+ }
+
+ collection_compiler = new ComputationCompiler(compiler);
+
+ n.get_collection().get_visited_by(collection_compiler);
+
+ if (collection_compiler.has_init())
+ {
+ result.add(collection_compiler.get_init());
+ }
+
+ result.add
+ (
+ new SetValue
+ (
+ index_holder.get_address(),
+ new IfElseComputation
+ (
+ Operation.greater_than
+ (
+ index_compiler.get_computation(),
+ new Size(collection_compiler.get_address())
+ ),
+ new Size(collection_compiler.get_address()),
+ index_compiler.get_computation()
+ )
+ )
+ );
+
+ result.add
+ (
+ InsertAt.generate
+ (
+ compiler.registers(),
+ compiler.assembler(),
+ index_holder.get_address(),
+ element_compiler.get_computation(),
+ new Size(collection_compiler.get_address()),
+ collection_compiler.get_address()
+ )
+ );
+
+ compiler.registers().release(index_holder);
+
+ index_compiler.release_registers();
+ element_compiler.release_registers();
+ collection_compiler.release_registers();
+ }
+
+ @Override
public void visit_add_element
(
final tonkadur.fate.v1.lang.instruction.AddElement ae
diff --git a/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/TypeCompiler.java b/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/TypeCompiler.java
index 177be18..3792080 100644
--- a/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/TypeCompiler.java
+++ b/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/TypeCompiler.java
@@ -176,32 +176,6 @@ public class TypeCompiler
return MapType.MAP_TO_INT;
}
- if (fate_content_type instanceof tonkadur.fate.v1.lang.type.PointerType)
- {
- return
- new MapType
- (
- new PointerType
- (
- compile
- (
- compiler,
- (
- (tonkadur.fate.v1.lang.type.PointerType)
- fate_content_type
- ).get_referenced_type()
- )
- )
- );
- }
-
- System.err.println
- (
- "[P] Unknown collection member fate type '"
- + fate_content_type
- + "'."
- );
-
- return null;
+ return new MapType(compile(compiler, fate_content_type));
}
}