| summaryrefslogtreecommitdiff | 
diff options
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));     }  } | 


