From 7cb11f919083225942ab02c9bc5c6f0ed04a8a55 Mon Sep 17 00:00:00 2001 From: npgit Date: Tue, 17 Dec 2024 16:14:55 -0500 Subject: [PATCH 1/3] Switch named operators from :{curly} to :(paren) --- ayarc.aya | 2 +- base/__aya__.aya | 8 +- base/importlib.aya | 6 +- examples/ayarc_eclipse.aya | 6 +- examples/canvas/cube.aya | 8 +- examples/canvas/graphics.aya | 96 +++++++++---------- examples/plot/box_plot.aya | 4 +- examples/plot/canvas_multiplot.aya | 6 +- examples/plot/iris.aya | 2 +- examples/plot/pie_chart.aya | 4 +- manual/canvas_input.md | 10 +- manual/multithreading.md | 2 +- manual/syntax_overview.md | 4 +- src/aya/TypeIDs.java | 2 +- src/aya/ext/color/ColorInstructionStore.java | 2 +- .../ext/dialog/DialogInstructionStore.java | 6 +- .../instruction/NewGraphicsInstruction.java | 2 +- .../instruction/PathGraphicsInstruction.java | 4 +- src/aya/ext/image/AyaImage.java | 4 +- .../instruction/ReadImageInstruction.java | 2 +- .../instruction/WriteImageInstruction.java | 2 +- src/aya/ext/la/MatMulInstruction.java | 4 +- src/aya/ext/sys/SystemInstructionStore.java | 16 ++-- .../named/NamedInstructionStore.java | 2 +- src/aya/instruction/named/NamedOperator.java | 2 +- src/aya/parser/Parser.java | 8 +- src/aya/parser/tokens/NamedOpToken.java | 2 +- std/canvas.aya | 72 +++++++------- std/color.aya | 6 +- std/date.aya | 38 ++++---- std/dialog.aya | 26 ++--- std/docstr.aya | 2 +- std/golf.aya | 2 +- std/image.aya | 4 +- std/io.aya | 38 ++++---- std/json.aya | 4 +- std/la.aya | 2 +- std/matrix.aya | 2 +- std/plot.aya | 4 +- std/shell.aya | 2 +- std/socket.aya | 24 ++--- std/sys.aya | 8 +- std/terminal.aya | 2 +- std/threading.aya | 10 +- test/examples.aya | 2 +- test/filesystem.aya | 82 ++++++++-------- test/test.aya | 4 +- 47 files changed, 275 insertions(+), 275 deletions(-) diff --git a/ayarc.aya b/ayarc.aya index 143dbcc1..7b659e15 100644 --- a/ayarc.aya +++ b/ayarc.aya @@ -1 +1 @@ -:{sys.ad} "base/__aya__.aya" + :F +:(sys.ad) "base/__aya__.aya" + :F diff --git a/base/__aya__.aya b/base/__aya__.aya index d9ea99a8..15daa3d3 100644 --- a/base/__aya__.aya +++ b/base/__aya__.aya @@ -7,7 +7,7 @@ .# NOTE: 12 letter variables ending in the letter 'z' are reserved for use in .# standard library. Such variables are used below. -{:{sys.ad} "test/test.aya" + :F}:tt; +{:(sys.ad) "test/test.aya" + :F}:tt; .# Global __aya__ table {, @@ -41,7 +41,7 @@ .#? bp\n set a breakpoint { : __aya__^, __aya__.ignore_breakpoints ! { - :{debug.pause} + :(debug.pause) } ? }:bp; @@ -66,7 +66,7 @@ .# ------- {name, - [:{sys.ad} :9s "examples" :9s name ".aya"] W :F + [:(sys.ad) :9s "examples" :9s name ".aya"] W :F }:example; @@ -448,5 +448,5 @@ __aya__.extend.` :extend; ] :# {f, .# "Loading base/$f..." :P - load ([:{sys.ad} :9s "base/$f"]W) + load ([:(sys.ad) :9s "base/$f"]W) }; diff --git a/base/importlib.aya b/base/importlib.aya index 1d8bc343..d481c81a 100644 --- a/base/importlib.aya +++ b/base/importlib.aya @@ -6,7 +6,7 @@ def importlib::_log_debug {:importlib^, importlib._debug {"importlib: " \+ :P} {;} .? } -def importlib::aya_dir :{sys.ad} +def importlib::aya_dir :(sys.ad) .# Dictionary of files which have been imported def importlib::imported {,} @@ -18,7 +18,7 @@ def importlib::path [ .# Return the path with the current directory at the bottom def importlib::get_path { : importlib^ , importlib.path - :{sys.wd} + :(sys.wd) J } @@ -138,7 +138,7 @@ def importlib::from_file {filepath : importlib^ all_possible mod, importlib.get_path :# { filepath + } :~ :all_possible .# Get only files that exist - { :{sys.file_exists} } I + { :(sys.file_exists) } I .# If the lists is empty, throw an error .E 0 = {"Import Error: Unable to find any of the following files: $all_possible" .D} ? diff --git a/examples/ayarc_eclipse.aya b/examples/ayarc_eclipse.aya index 2a577960..d5fb7639 100644 --- a/examples/ayarc_eclipse.aya +++ b/examples/ayarc_eclipse.aya @@ -5,13 +5,13 @@ .# cp examples/ayarc_eclipse.aya target/classes/ayarc.aya .# The current working directory, split on path separator -:{sys.wd} '/ S +:(sys.wd) '/ S .# Pop 2 dirs {B ;} 2 % .# Re-assemble the path #"/"+ W .# Set as current dir and aya dir -$ :{sys.cd} :{sys.set_ad} +$ :(sys.cd) :(sys.set_ad) .# Load ayarc from the normal place -:{sys.wd} "ayarc.aya" + :F +:(sys.wd) "ayarc.aya" + :F diff --git a/examples/canvas/cube.aya b/examples/canvas/cube.aya index 07bcf095..27c3a738 100644 --- a/examples/canvas/cube.aya +++ b/examples/canvas/cube.aya @@ -76,10 +76,10 @@ points 70 * :points; .# Rotate the points points :points_rotated; - rotation_y points_rotated :{la.mul} :points_rotated; - rotation_x points_rotated :{la.mul} :points_rotated; - rotation_z points_rotated :{la.mul} :points_rotated; - projection points_rotated :{la.mul} :points_projected; + rotation_y points_rotated :(la.mul) :points_rotated; + rotation_x points_rotated :(la.mul) :points_rotated; + rotation_z points_rotated :(la.mul) :points_rotated; + projection points_rotated :(la.mul) :points_projected; .# Apply canvas transform .# (Move the points to the center of the canvas) diff --git a/examples/canvas/graphics.aya b/examples/canvas/graphics.aya index e718b8a8..625d5510 100644 --- a/examples/canvas/graphics.aya +++ b/examples/canvas/graphics.aya @@ -1,4 +1,4 @@ -{g :{graphics.close}; } {;} .K +{g :(graphics.close); } {;} .K .{ A Demo of all raw graphics calls that can be made @@ -9,87 +9,87 @@ {,255Q:r 255Q:g 255Q:b}:col; {,100:r 100:g 100:b}:col; {x y, - 1 g :{graphics.set_stroke_width} - 0 0 0 g :{graphics.set_color} - x y x y g :{graphics.line} + 1 g :(graphics.set_stroke_width) + 0 0 0 g :(graphics.set_color) + x y x y g :(graphics.line) }:point; -{, 300:width 300:height "Test":name 1:autoflush 1:show} :{graphics.new} :g; +{, 300:width 300:height "Test":name 1:autoflush 1:show} :(graphics.new) :g; 200 200 point -0 0 100 200 g :{graphics.line} -150 0 150 300 g :{graphics.line} -0 150 300 150 g :{graphics.line} +0 0 100 200 g :(graphics.line) +150 0 150 300 g :(graphics.line) +0 150 300 150 g :(graphics.line) .# x1 y1 w h fill -20 30 10 100 0 g :{graphics.rect} +20 30 10 100 0 g :(graphics.rect) .# r g b -200 0 0 g :{graphics.set_color} -3 g :{graphics.set_stroke_width} -40 40 0 50 g :{graphics.line} -120 130 10 50 1 g :{graphics.rect} -200 250 0 g :{graphics.set_color} +200 0 0 g :(graphics.set_color) +3 g :(graphics.set_stroke_width) +40 40 0 50 g :(graphics.line) +120 130 10 50 1 g :(graphics.rect) +200 250 0 g :(graphics.set_color) .# x y w h dh dv fill -50 50 50 50 30 15 1 g :{graphics.round_rect} -45 45 60 60 15 30 0 g :{graphics.round_rect} -col.r col.g col.b g :{graphics.set_color} -200 200 50 50 1 g :{graphics.oval} -194 194 61 61 0 g :{graphics.oval} -150 150 40 60 0 g :{graphics.ellipse} +50 50 50 50 30 15 1 g :(graphics.round_rect) +45 45 60 60 15 30 0 g :(graphics.round_rect) +col.r col.g col.b g :(graphics.set_color) +200 200 50 50 1 g :(graphics.oval) +194 194 61 61 0 g :(graphics.oval) +150 150 40 60 0 g :(graphics.ellipse) .# x y w h angle extent fill -150 150 100 100 0 90 0 g :{graphics.arc} -150 150 100 100 90 90 1 g :{graphics.arc} +150 150 100 100 0 90 0 g :(graphics.arc) +150 150 100 100 90 90 1 g :(graphics.arc) -0 0 0 g :{graphics.set_color} -1 g :{graphics.set_stroke_width} -250 0 250 300 g :{graphics.line} -100 100 0 g :{graphics.set_color} -5 g :{graphics.set_stroke_width} +0 0 0 g :(graphics.set_color) +1 g :(graphics.set_stroke_width) +250 0 250 300 g :(graphics.line) +100 100 0 g :(graphics.set_color) +5 g :(graphics.set_stroke_width) 1:idx; ["butt" "round" "square"] :# {cap, - 5 cap "bevel" g :{graphics.set_stroke} - 150 idx20* 250 idx20* g :{graphics.line} + 5 cap "bevel" g :(graphics.set_stroke) + 150 idx20* 250 idx20* g :(graphics.line) ::idx B }; -5 g :{graphics.set_stroke_width} -col.r col.g col.b g :{graphics.set_color} +5 g :(graphics.set_stroke_width) +col.r col.g col.b g :(graphics.set_color) ["bevel" "miter" "round"] :# {join, - 5 "square" join g :{graphics.set_stroke} - 150 idx30* 100 15 0 g :{graphics.rect} + 5 "square" join g :(graphics.set_stroke) + 150 idx30* 100 15 0 g :(graphics.rect) ::idx B }; .# x1 y1 x2 y2 start_r start_g start_b start_a end_r end_g end_b end_a cycle -0 0 20 20 (255 0 0 200) (0 255 0 200) 1 g :{graphics.set_paint_grad} +0 0 20 20 (255 0 0 200) (0 255 0 200) 1 g :(graphics.set_paint_grad) -0.4 g :{graphics.set_alpha} +0.4 g :(graphics.set_alpha) [ 0 75 100 125 200 150 160 100 40 50 0 ] [ 85 75 10 75 85 125 190 150 190 125 85 ] -1 g :{graphics.path} +1 g :(graphics.path) -0 0 0 1.0 g :{graphics.set_color_alpha} -2 g :{graphics.set_stroke_width} +0 0 0 1.0 g :(graphics.set_color_alpha) +2 g :(graphics.set_stroke_width) [ 0 75 100 125 200 150 160 100 40 50 0 ] [ 85 75 10 75 85 125 190 150 190 125 85 ] -0 g :{graphics.path} +0 g :(graphics.path) 225 225 point 260 260 point .# fonts -0 0 0 1.0 g :{graphics.set_color_alpha} -"Hello world!" 20 20 g :{graphics.text} +0 0 0 1.0 g :(graphics.set_color_alpha) +"Hello world!" 20 20 g :(graphics.text) -"Times New Roman" "bold" 20 g :{graphics.set_font} +"Times New Roman" "bold" 20 g :(graphics.set_font) -"Hello world!" 20 40 g :{graphics.text} +"Hello world!" 20 40 g :(graphics.text) -col.r col.g col.b g :{graphics.set_color} -"Comic Sans MS" "italic" 15 g :{graphics.set_font} -"Hello world!" 20 60 g :{graphics.text} +col.r col.g col.b g :(graphics.set_color) +"Comic Sans MS" "italic" 15 g :(graphics.set_font) +"Hello world!" 20 60 g :(graphics.text) -"Courier New" "bolditalic" 24 g :{graphics.set_font} -"Hello world!" 20 80 g :{graphics.text} +"Courier New" "bolditalic" 24 g :(graphics.set_font) +"Hello world!" 20 80 g :(graphics.text) diff --git a/examples/plot/box_plot.aya b/examples/plot/box_plot.aya index d0b41349..386c3e98 100644 --- a/examples/plot/box_plot.aya +++ b/examples/plot/box_plot.aya @@ -7,7 +7,7 @@ {, 15.R :values} {, 10.R :values} ] :data -} :{plot.box_plot} +} :(plot.box_plot) .{ An example showing all parameters for box-plots .} @@ -43,4 +43,4 @@ {, [0 0.9 1 1.1 2] 0.5 + :values "group2" :group "2" :entry} {, [0 0.9 1 1.1 2] 0.6 + :values "group2" :group "3" :entry} ] :data -} :{plot.box_plot} +} :(plot.box_plot) diff --git a/examples/plot/canvas_multiplot.aya b/examples/plot/canvas_multiplot.aya index ac2e466e..08ae3d1e 100644 --- a/examples/plot/canvas_multiplot.aya +++ b/examples/plot/canvas_multiplot.aya @@ -17,7 +17,7 @@ import ::canvas } :canvas 400 :width :height [0 1 2 1 0] # {x, {, x 5* 10+ .R :values}} :data -} :{plot.box_plot} +} :(plot.box_plot) .{ Add a pie-chart in the bottom-left corner .} {, @@ -29,7 +29,7 @@ import ::canvas } :canvas 400 :width :height [1 3 6] :data -} :{plot.pie_chart} +} :(plot.pie_chart) .{ Add a multiplot in the right half .} {, @@ -61,7 +61,7 @@ import ::canvas ] :data } ] :subplots -} :{plot.multiplot} +} :(plot.multiplot) c.show c.wait \ No newline at end of file diff --git a/examples/plot/iris.aya b/examples/plot/iris.aya index 7444f50d..5115a41d 100644 --- a/examples/plot/iris.aya +++ b/examples/plot/iris.aya @@ -1,7 +1,7 @@ import ::dataframe import ::plot -{, "$(:{sys.ad})/examples/data/iris.csv":filename} dataframe.read_csv :df; +{, "$(:(sys.ad))/examples/data/iris.csv":filename} dataframe.read_csv :df; .# get unique species names df.["Species"] :~ :species; diff --git a/examples/plot/pie_chart.aya b/examples/plot/pie_chart.aya index e59656b4..5a827d6a 100644 --- a/examples/plot/pie_chart.aya +++ b/examples/plot/pie_chart.aya @@ -1,7 +1,7 @@ .{ An example of the minimum required parameters for drawing a box-plot .} {, [1 3 6] :data -} :{plot.pie_chart} +} :(plot.pie_chart) {, "An Example Pie-Chart" :title @@ -17,4 +17,4 @@ {, 3:value "b":label } {, 6:value "c":label } ]:data -} :{plot.pie_chart} +} :(plot.pie_chart) diff --git a/manual/canvas_input.md b/manual/canvas_input.md index 7cc41422..257c094f 100644 --- a/manual/canvas_input.md +++ b/manual/canvas_input.md @@ -21,7 +21,7 @@ Lists the mouse clicks since the last time this instruction was executed. - `clicks` (num) The amount of successive clicks. (Useful for detecting double-clicks) ``` -aya> my_canvas.id :{graphics.click_events} +aya> my_canvas.id :(graphics.click_events) [ { 128 :x; 256 :y; @@ -37,7 +37,7 @@ Lists the currently held mouse buttons. `graphics.pressed_buttons` pushes a list of currently held button-numbers onto the stack. (See [Mouse Buttons](#mouse-buttons)) ``` -aya> my_canvas.id :{graphics.pressed_buttons} +aya> my_canvas.id :(graphics.pressed_buttons) [ 1 3 ] ``` @@ -51,7 +51,7 @@ Lists the mouse movements since the last time this instruction was executed. - `y` (num) The y-coordinate the cursor moved to. ``` -aya> my_canvas.id :{graphics.move_events} +aya> my_canvas.id :(graphics.move_events) [ { 128 :x; 256 :y; @@ -78,7 +78,7 @@ Lists the currently held keyboard keys. - `location` (num) An integer representation of the location. ``` -aya> my_canvas.id :{graphics.pressed_keys} +aya> my_canvas.id :(graphics.pressed_keys) [ { "A" :key_name; 65 :keycode; @@ -99,7 +99,7 @@ Lists the Unicode characters that were typed since the last time this instructio `graphics.typed_chars` pushes a string of typed characters onto the stack. ``` -aya> my_canvas.id :{graphics.typed_chars} +aya> my_canvas.id :(graphics.typed_chars) "Hello, World!" ``` diff --git a/manual/multithreading.md b/manual/multithreading.md index 83d374ee..50d3c974 100644 --- a/manual/multithreading.md +++ b/manual/multithreading.md @@ -50,7 +50,7 @@ aya> t.wait_for_result > File '/home/npaul/git/aya/std/threading.aya', line 16, col 37: 15 | def thread::wait_for_result {self, -16 | self.id :{thread.wait_for_result} +16 | self.id :(thread.wait_for_result) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ 17 | } diff --git a/manual/syntax_overview.md b/manual/syntax_overview.md index bfa5164f..0a62b721 100644 --- a/manual/syntax_overview.md +++ b/manual/syntax_overview.md @@ -831,10 +831,10 @@ aya> {P} 2 :` 1 + ### Extension Operators -Extension operators have the form `:{...}`. +Extension operators have the form `:(...)`. ``` -aya> 123456789 "dd/MM/yyyy HH:mm:ss" :{date.format} +aya> 123456789 "dd/MM/yyyy HH:mm:ss" :(date.format) "02/01/1970 05:17:36" ``` diff --git a/src/aya/TypeIDs.java b/src/aya/TypeIDs.java index 30f4e66f..eef8c79f 100644 --- a/src/aya/TypeIDs.java +++ b/src/aya/TypeIDs.java @@ -32,5 +32,5 @@ public class TypeIDs { public static final byte T_DOT_COLON = 125; // (.:) dot colon operator public static final byte T_FN_QUOTE = 126; // (.`) function quote public static final byte T_COLON_POUND = 127; // (:#) special operator - public static final byte T_NAMED_OP = 90; // :{...} + public static final byte T_NAMED_OP = 90; // :(...) } diff --git a/src/aya/ext/color/ColorInstructionStore.java b/src/aya/ext/color/ColorInstructionStore.java index 34cd300f..c0fa5148 100644 --- a/src/aya/ext/color/ColorInstructionStore.java +++ b/src/aya/ext/color/ColorInstructionStore.java @@ -30,7 +30,7 @@ public void execute(BlockEvaluator blockEvaluator) { d.set(SymbolConstants.A, Num.fromInt(color.getAlpha())); blockEvaluator.push(d); } catch (IllegalArgumentException e) { - throw new ValueError(":{color.fromstr} Invalid color: '" + color_str + "'"); + throw new ValueError(":(color.fromstr) Invalid color: '" + color_str + "'"); } } }); diff --git a/src/aya/ext/dialog/DialogInstructionStore.java b/src/aya/ext/dialog/DialogInstructionStore.java index d5da7b21..13f65dd4 100644 --- a/src/aya/ext/dialog/DialogInstructionStore.java +++ b/src/aya/ext/dialog/DialogInstructionStore.java @@ -63,7 +63,7 @@ public void execute(BlockEvaluator blockEvaluator) { int type = symToDialogType((Symbol)type_obj); List options = asList(options_obj); - if (options.length() != 2) throw new ValueError(":{dialog.confirm} : Expected options list of length 2. Got " + options.repr()); + if (options.length() != 2) throw new ValueError(":(dialog.confirm) : Expected options list of length 2. Got " + options.repr()); boolean val = QuickDialog.confirm( message_obj.str(), @@ -89,7 +89,7 @@ public void execute(BlockEvaluator blockEvaluator) { int type = symToDialogType((Symbol)type_obj); List options_list = asList(options_obj); - if (options_list.length() <= 0) throw new ValueError(":{dialog.buttons} : Expected non-empty options. Got " + options_list.repr()); + if (options_list.length() <= 0) throw new ValueError(":(dialog.buttons) : Expected non-empty options. Got " + options_list.repr()); String[] options = new String[options_list.length()]; for (int i = 0; i < options_list.length(); i++) { @@ -119,7 +119,7 @@ public void execute(BlockEvaluator blockEvaluator) { int type = symToDialogType((Symbol)type_obj); List options_list = asList(options_obj); - if (options_list.length() <= 0) throw new ValueError(":{dialog.buttons} : Expected non-empty options. Got " + options_list.repr()); + if (options_list.length() <= 0) throw new ValueError(":(dialog.buttons) : Expected non-empty options. Got " + options_list.repr()); String[] options = new String[options_list.length()]; for (int i = 0; i < options_list.length(); i++) { diff --git a/src/aya/ext/graphics/instruction/NewGraphicsInstruction.java b/src/aya/ext/graphics/instruction/NewGraphicsInstruction.java index e1c59d86..9e1057f7 100644 --- a/src/aya/ext/graphics/instruction/NewGraphicsInstruction.java +++ b/src/aya/ext/graphics/instruction/NewGraphicsInstruction.java @@ -24,7 +24,7 @@ public void execute(BlockEvaluator blockEvaluator) { if (o_params.isa(Obj.DICT)) { DictReader params = new DictReader(Casting.asDict(o_params)); - params.setErrorName(":{graphics.new}"); + params.setErrorName(":(graphics.new)"); int id = _canvas_table.newCanvas(params.getString(SymbolConstants.NAME, "Canvas"), params.getIntEx(SymbolConstants.WIDTH), params.getIntEx(SymbolConstants.HEIGHT), diff --git a/src/aya/ext/graphics/instruction/PathGraphicsInstruction.java b/src/aya/ext/graphics/instruction/PathGraphicsInstruction.java index 4292559f..829ac0fc 100644 --- a/src/aya/ext/graphics/instruction/PathGraphicsInstruction.java +++ b/src/aya/ext/graphics/instruction/PathGraphicsInstruction.java @@ -24,13 +24,13 @@ protected void doCanvasCommand(Canvas cvs, BlockEvaluator blockEvaluator) { if (xs.length != ys.length) { throw new ValueError( - ":{graphics.path} : 'xs' and 'ys' must be the same length. Got xs(" + + ":(graphics.path) : 'xs' and 'ys' must be the same length. Got xs(" + xs.length + "), ys(" + ys.length + ")"); } if (xs.length == 0) { throw new ValueError( - ":{graphics.path} : 'xs' and 'ys' must contain at least 1 point."); + ":(graphics.path) : 'xs' and 'ys' must contain at least 1 point."); } GeneralPath path = new GeneralPath(); diff --git a/src/aya/ext/image/AyaImage.java b/src/aya/ext/image/AyaImage.java index ac8b8e3f..435fbab3 100644 --- a/src/aya/ext/image/AyaImage.java +++ b/src/aya/ext/image/AyaImage.java @@ -22,8 +22,8 @@ *
{@code
  * {,
  *     .# meta information about the image.
- *     .# :{image.read} provides this information
- *     .# :{image.write} infers these values unless specified
+ *     .# :(image.read) provides this information
+ *     .# :(image.write) infers these values unless specified
  *     {,
  *          :gray
  *          :alpha
diff --git a/src/aya/ext/image/instruction/ReadImageInstruction.java b/src/aya/ext/image/instruction/ReadImageInstruction.java
index 1c0803cd..224a9ffd 100644
--- a/src/aya/ext/image/instruction/ReadImageInstruction.java
+++ b/src/aya/ext/image/instruction/ReadImageInstruction.java
@@ -17,7 +17,7 @@ public class ReadImageInstruction extends NamedOperator {
 	public ReadImageInstruction() {
 		super("image.read");
 		_doc = ("Read an image from a file\n"
-				+ "  \n"
+				+ "  \n"
 				+ "  "
 		);
 	}
diff --git a/src/aya/ext/image/instruction/WriteImageInstruction.java b/src/aya/ext/image/instruction/WriteImageInstruction.java
index 6f4c1a3e..a49d5723 100644
--- a/src/aya/ext/image/instruction/WriteImageInstruction.java
+++ b/src/aya/ext/image/instruction/WriteImageInstruction.java
@@ -21,7 +21,7 @@ public class WriteImageInstruction extends NamedOperator {
 	public WriteImageInstruction() {
 		super("image.write");
 		_doc = ("image::dict filename::str : write image to file\n"
-				+ "  \n"
+				+ "  \n"
 				+ "  image::dict : " + AyaImage.getDocString("    ")
 				+ "  filename::str : name of the file to write to. The file extension controls the image type."
 		);
diff --git a/src/aya/ext/la/MatMulInstruction.java b/src/aya/ext/la/MatMulInstruction.java
index d341cf38..3d590f7a 100644
--- a/src/aya/ext/la/MatMulInstruction.java
+++ b/src/aya/ext/la/MatMulInstruction.java
@@ -40,9 +40,9 @@ private List matMulSafe(List a, List b) {
 		} catch (ClassCastException e0) {
 			throw new TypeError(this, "LL", b, a);
 		} catch (IndexError e1) {
-			throw new ValueError("Dimension error in :{la.mul}");
+			throw new ValueError("Dimension error in :(la.mul)");
 		} catch (IndexOutOfBoundsException e2) {
-			throw new ValueError("Dimension error in :{la.mul}");
+			throw new ValueError("Dimension error in :(la.mul)");
 		}
 	}
 	
diff --git a/src/aya/ext/sys/SystemInstructionStore.java b/src/aya/ext/sys/SystemInstructionStore.java
index b0728283..a4ad4ad1 100644
--- a/src/aya/ext/sys/SystemInstructionStore.java
+++ b/src/aya/ext/sys/SystemInstructionStore.java
@@ -36,7 +36,7 @@ public void execute(BlockEvaluator blockEvaluator) {
 					}
 					blockEvaluator.push(new List(obj_dirs));
 				} else {
-					throw new ValueError(":{sys.readdir} : arg must be a string. Received:\n" + arg.repr());
+					throw new ValueError(":(sys.readdir) : arg must be a string. Received:\n" + arg.repr());
 				}
 			}
 		});
@@ -77,12 +77,12 @@ public void execute(BlockEvaluator blockEvaluator) {
 						AyaPrefs.resetWorkingDir();
 					} else {
 						if (!AyaPrefs.setWorkingDir(arg.str())) {
-							throw new ValueError(":{sys.cd} : arg is not a valid path."
+							throw new ValueError(":(sys.cd) : arg is not a valid path."
 									+ " Did you include a '/' or '\' at the end? Received:\n" + arg.repr());
 						}
 					}
 				} else {
-					throw new ValueError(":{sys.cd} : arg must be a string. Received:\n" + arg.repr());
+					throw new ValueError(":(sys.cd) : arg must be a string. Received:\n" + arg.repr());
 				}
 			}
 		});
@@ -96,10 +96,10 @@ public void execute(BlockEvaluator blockEvaluator) {
 				if(arg.isa(Obj.STR)) {
 					String fstr = arg.str();
 					if(!AyaPrefs.mkDir(fstr)) {
-						throw new ValueError(":{sys.mkdir} : arg must be a valid name. Received:\n" + fstr);
+						throw new ValueError(":(sys.mkdir) : arg must be a valid name. Received:\n" + fstr);
 					}
 				} else {
-					throw new ValueError(":{sys.mkdir} : arg must be a string. Received:\n" + arg.repr());
+					throw new ValueError(":(sys.mkdir) : arg must be a string. Received:\n" + arg.repr());
 				}
 			}
 		});
@@ -128,14 +128,14 @@ public void execute(BlockEvaluator blockEvaluator) {
 				if(arg.isa(Obj.STR)) {
 					String arg_str = arg.str();
 					if(arg_str.equals("")) {
-						throw new ValueError(":{sys.rm} : arg must be a valid name. Received:\n" + arg_str);
+						throw new ValueError(":(sys.rm) : arg must be a valid name. Received:\n" + arg_str);
 					}
 					File delFile = FileUtils.resolveFile(arg.str());
 					if(!AyaPrefs.deleteFile(delFile)) {
-						throw new ValueError(":{sys.rm} : arg must be a valid name. Received:\n" + delFile.getAbsolutePath());
+						throw new ValueError(":(sys.rm) : arg must be a valid name. Received:\n" + delFile.getAbsolutePath());
 					}
 				} else {
-					throw new ValueError(":{sys.rm} : arg must be a string. Received:\n" + arg.repr());
+					throw new ValueError(":(sys.rm) : arg must be a string. Received:\n" + arg.repr());
 				}
 			}
 		});
diff --git a/src/aya/instruction/named/NamedInstructionStore.java b/src/aya/instruction/named/NamedInstructionStore.java
index c28272c5..5dd3caef 100644
--- a/src/aya/instruction/named/NamedInstructionStore.java
+++ b/src/aya/instruction/named/NamedInstructionStore.java
@@ -26,7 +26,7 @@ public void initHelpData(StaticData staticData) {
 			NamedOperator i = pair.getValue();
 			String doc = i._doc;
 			if (doc == null || doc.equals("")) continue;
-			staticData.addHelpText(":{" + i.getName() + "}\n  " + doc);
+			staticData.addHelpText(":(" + i.getName() + ")\n  " + doc);
 		}
 	}
 	
diff --git a/src/aya/instruction/named/NamedOperator.java b/src/aya/instruction/named/NamedOperator.java
index 51fd2323..6a1ce1c1 100644
--- a/src/aya/instruction/named/NamedOperator.java
+++ b/src/aya/instruction/named/NamedOperator.java
@@ -25,7 +25,7 @@ public String getName() {
 	}
 	
 	public String opName() {
-		return ":{" + _name + "}";
+		return ":(" + _name + ")";
 	}
 
 	public ReprStream repr(ReprStream stream) {
diff --git a/src/aya/parser/Parser.java b/src/aya/parser/Parser.java
index 36740d02..b35d5fd0 100644
--- a/src/aya/parser/Parser.java
+++ b/src/aya/parser/Parser.java
@@ -369,13 +369,13 @@ else if (current == ':') {
 					}
 					
 					// Named Operator
-					else if (in.peek() == '{') {
-						in.next(); // Skip '{'
+					else if (in.peek() == '(') {
+						in.next(); // Skip '('
 						StringBuilder sb = new StringBuilder();
 						boolean done = false;
 						while (in.hasNext()) {
 							char c = in.next();
-							if (c == '}') {
+							if (c == ')') {
 								done = true;
 								break;
 							} else {
@@ -385,7 +385,7 @@ else if (in.peek() == '{') {
 						if (done) {
 							tokens.add(new NamedOpToken(sb.toString(), in.currentRef()));
 						} else {
-							throw new SyntaxError("Expected '}' after :{" + sb.toString(), in.currentRef());
+							throw new SyntaxError("Expected ')' after :(" + sb.toString(), in.currentRef());
 						}
 					}
 
diff --git a/src/aya/parser/tokens/NamedOpToken.java b/src/aya/parser/tokens/NamedOpToken.java
index 2a396361..2ecf2fbf 100644
--- a/src/aya/parser/tokens/NamedOpToken.java
+++ b/src/aya/parser/tokens/NamedOpToken.java
@@ -19,7 +19,7 @@ public Instruction getInstruction() throws ParserException {
 		if (instruction != null) {
 			return new NamedOperatorInstruction(this.getSourceStringRef(), instruction);
 		} else {
-			throw new ParserException("Named instruction :{" + data + "} does not exist", source);
+			throw new ParserException("Named instruction :(" + data + ") does not exist", source);
 		}
 	}
 
diff --git a/std/canvas.aya b/std/canvas.aya
index 7edf643b..75ebbff1 100644
--- a/std/canvas.aya
+++ b/std/canvas.aya
@@ -25,8 +25,8 @@ def canvas::__init__ {params::dict self : color^,
     .# Input
     [-1 -1] self.:_last_mouse_pos;
 
-    .# ::new params 0 :{graphics.MG} self.:id ;
-    params :{graphics.new} self.:id ;
+    .# ::new params 0 :(graphics.MG) self.:id ;
+    params :(graphics.new) self.:id ;
 }
 
 def canvas::__str__ {self,
@@ -40,43 +40,43 @@ def canvas::delay {self,
 }
 
 def canvas::line {xa ya xb yb self,
-    .# ::line {, xa:xa ya:ya xb:xb yb:yb } self.id :{graphics.MG} ;
-    xa ya xb yb self.id :{graphics.line}
+    .# ::line {, xa:xa ya:ya xb:xb yb:yb } self.id :(graphics.MG) ;
+    xa ya xb yb self.id :(graphics.line)
 }
 
 def canvas::path {xs::list ys::list fill::num self,
-    xs ys fill self.id :{graphics.path}
+    xs ys fill self.id :(graphics.path)
 }
 
 def canvas::point {x y self,
-    .#::line {, x:xa:xb y:ya:yb} self.id :{graphics.MG} ;
-    x y x y self.id :{graphics.line}
+    .#::line {, x:xa:xb y:ya:yb} self.id :(graphics.MG) ;
+    x y x y self.id :(graphics.line)
 }
 
 def canvas::circle {x y r self,
-    x y r2* $ 0 self.id :{graphics.ellipse}
+    x y r2* $ 0 self.id :(graphics.ellipse)
 }
 
 def canvas::fillcircle {x y r self,
-    x y r2* $ 1 self.id :{graphics.ellipse}
+    x y r2* $ 1 self.id :(graphics.ellipse)
 }
 
 def canvas::points {points r self,
-    points r2* $ self.id :{graphics.points}
+    points r2* $ self.id :(graphics.points)
 }
 
 def canvas::set_color {color self,
-    .# ::set_color {, color.r:r color.g:g color.b:b } self.id :{graphics.MG} ;
-    color.r color.g color.b self.id :{graphics.set_color}
+    .# ::set_color {, color.r:r color.g:g color.b:b } self.id :(graphics.MG) ;
+    color.r color.g color.b self.id :(graphics.set_color)
 }
 
 def canvas::set_alpha {a self,
-    .# ::set_alpha {, a:a } self.id :{graphics.MG} ;
-    a self.id :{graphics.set_alpha}
+    .# ::set_alpha {, a:a } self.id :(graphics.MG) ;
+    a self.id :(graphics.set_alpha)
 }
 
 def canvas::set_stroke_width {n::num self,
-    n self.id :{graphics.set_stroke_width}
+    n self.id :(graphics.set_stroke_width)
 }
 
 def canvas::cap {,}
@@ -90,19 +90,19 @@ def canvas::join {,}
 "round" canvas.join.:round;
 
 def canvas::set_stroke {width::num cap::str join::str self,
-    width cap join self.id :{graphics.set_stroke}
+    width cap join self.id :(graphics.set_stroke)
 }
 
 def canvas::set_grad {start::list ca::color end::list cb::color cycle::num self,
     start.[0] start.[1] end.[0] end.[1]
     ca.r ca.g ca.b ca.a 255*
     cb.r cb.g cb.b cb.a 255*
-    cycle self.id :{graphics.set_paint_grad}
+    cycle self.id :(graphics.set_paint_grad)
 }
 
 def canvas::set_bg {color self,
-    .# ::set_bg {, color.r:r color.g:g color.b:b } self.id :{graphics.MG} ;
-    color.r color.g color.b self.id :{graphics.set_bgcolor}
+    .# ::set_bg {, color.r:r color.g:g color.b:b } self.id :(graphics.MG) ;
+    color.r color.g color.b self.id :(graphics.set_bgcolor)
 }
 
 def canvas::save {filename self,
@@ -111,38 +111,38 @@ def canvas::save {filename self,
     .# Add file extension if it does not exist
     ".png" filename.in ! {".png"+} ?
 
-    self.id :{graphics.save}
+    self.id :(graphics.save)
 }
 
 def canvas::close {self,
-    .# ::close {,} self.id :{graphics.MG} ;
-    self.id :{graphics.close}
+    .# ::close {,} self.id :(graphics.MG) ;
+    self.id :(graphics.close)
 }
 
 def canvas::show {self,
-    self.id :{graphics.show}
+    self.id :(graphics.show)
 }
 
 def canvas::isopen {self,
-    self.id :{graphics.isopen}
+    self.id :(graphics.isopen)
 }
 
 def canvas::rect {x y w h self,
-    .# ::rect {, x:x y:y w:w h:h } self.id :{graphics.MG} ;
-    x y w h 0 self.id :{graphics.rect}
+    .# ::rect {, x:x y:y w:w h:h } self.id :(graphics.MG) ;
+    x y w h 0 self.id :(graphics.rect)
 }
 
 def canvas::fillrect {x y w h self,
-    .# ::rect {, x:x y:y w:w h:h 1:fill} self.id :{graphics.MG} ;
-    x y w h 1 self.id :{graphics.rect}
+    .# ::rect {, x:x y:y w:w h:h 1:fill} self.id :(graphics.MG) ;
+    x y w h 1 self.id :(graphics.rect)
 }
 
 def canvas::clear {self,
-    self.id :{graphics.clear}
+    self.id :(graphics.clear)
 }
 
 def canvas::viewmat {data self,
-    data self.id :{graphics.viewmat}
+    data self.id :(graphics.viewmat)
 }
 
 .# Block until the canvas is closed
@@ -151,7 +151,7 @@ def canvas::wait {self,
 }
 
 def canvas::move_events {self,
-    self.id :{graphics.move_events}
+    self.id :(graphics.move_events)
 }
 
 .# Get the most recent mouse x/y
@@ -165,22 +165,22 @@ def canvas::mouse_pos {self : move,
 }
 
 def canvas::pressed_buttons {self,
-    self.id :{graphics.pressed_buttons}
+    self.id :(graphics.pressed_buttons)
 }
 
 def canvas::typed_chars {self,
-    self.id :{graphics.typed_chars}
+    self.id :(graphics.typed_chars)
 }
 
 def canvas::pressed_keys {self,
-    self.id :{graphics.pressed_keys}
+    self.id :(graphics.pressed_keys)
 }
 
 def canvas::text {self,
-    self.id :{graphics.text}
+    self.id :(graphics.text)
 }
 
 def canvas::get_pixels {self : data image^,
-    self.id :{graphics.get_pixels} :data;
+    self.id :(graphics.get_pixels) :data;
     data.r data.g data.b data.a data.width data.height data.meta image!
 }
diff --git a/std/color.aya b/std/color.aya
index 7c6a90cc..93677639 100644
--- a/std/color.aya
+++ b/std/color.aya
@@ -32,7 +32,7 @@ def color::newhsv { color,
 }
 
 def color::fromstr { s::str color,
-    s :{color.fromstr} color.fromdict
+    s :(color.fromstr) color.fromdict
 }
 
 def color::fromdict { d::dict color ,
@@ -187,8 +187,8 @@ def color::rgbtohsv {r g b color : h s v delta maxv minv,
 module colors
 
 {,
-    :{color.name_list} :# {color_name : color_dict,
-        color_name :{color.fromstr} :color_dict;
+    :(color.name_list) :# {color_name : color_dict,
+        color_name :(color.fromstr) :color_dict;
         color_dict.r color_dict.g color_dict.b color! color_name :=
     }
 }:named_colors;
diff --git a/std/date.aya b/std/date.aya
index fd3723da..4149410e 100644
--- a/std/date.aya
+++ b/std/date.aya
@@ -18,7 +18,7 @@ export [::date ::dates ::dateunit]
 
     .# {in meta, [
     .#     in:T ::num = {{,in:ms} meta :M} ?
-    .#     in:T ::str = {{,in "yyyy-MM-dd" :{date.parse}:ms} meta :M} ?
+    .#     in:T ::str = {{,in "yyyy-MM-dd" :(date.parse):ms} meta :M} ?
     .#     {"Expected S|D, recieved: $in".D}
     .# ].S }:__new__;
 
@@ -30,7 +30,7 @@ export [::date ::dates ::dateunit]
                 } meta :M
             } (in :T ::str =) {
                 {, 
-                    in "yyyy-MM-dd" :{date.parse} :ms;
+                    in "yyyy-MM-dd" :(date.parse) :ms;
                 } meta :M
             } {
                 "Expected ::str or ::num. recieved: $in" .D
@@ -38,21 +38,21 @@ export [::date ::dates ::dateunit]
         } :?
     }:__new__;
 
-    {.ms "MMM dd, yyyy h:mm:ss a" :{date.format}}:__repr__;
+    {.ms "MMM dd, yyyy h:mm:ss a" :(date.format)}:__repr__;
     {.__repr__}:__str__;
 
-    {.ms :{date.desc}.day_of_week}:dayofweekid;
-    {.ms :{date.desc}.day_of_week dates.weekdays\V I}:dayofweek;
-    {.ms :{date.desc}.day_of_week dates.weekdaysabb\V I}:dayofweekabb;
-    {.ms :{date.desc}.year}:year;
-    {.ms :{date.desc}.month}:monthid;
-    {.ms :{date.desc}.month dates.monthnames\I}:month;
-    {.ms :{date.desc}.month dates.monthsabb\I}:monthabb;
-    {.ms :{date.desc}.day_of_month}:dayofmonth;
-    {.ms :{date.desc}.hour}:hour:h;
-    {.ms :{date.desc}.minute}:min:m;
-    {.ms :{date.desc}.second}:sec:s;
-    {.ms"a":{date.format}}:ampm;
+    {.ms :(date.desc).day_of_week}:dayofweekid;
+    {.ms :(date.desc).day_of_week dates.weekdays\V I}:dayofweek;
+    {.ms :(date.desc).day_of_week dates.weekdaysabb\V I}:dayofweekabb;
+    {.ms :(date.desc).year}:year;
+    {.ms :(date.desc).month}:monthid;
+    {.ms :(date.desc).month dates.monthnames\I}:month;
+    {.ms :(date.desc).month dates.monthsabb\I}:monthabb;
+    {.ms :(date.desc).day_of_month}:dayofmonth;
+    {.ms :(date.desc).hour}:hour:h;
+    {.ms :(date.desc).minute}:min:m;
+    {.ms :(date.desc).second}:sec:s;
+    {.ms"a":(date.format)}:ampm;
 
     {self unit,
         self.ms unit.ms + date!
@@ -65,12 +65,12 @@ export [::date ::dates ::dateunit]
     {.ms}:__sort__;
 
     .# Parse Functions
-    {"MM/dd/yy" :{date.parse}}:parsemdy;
+    {"MM/dd/yy" :(date.parse)}:parsemdy;
 
     .# String functions
-    {.ms "MM/dd/yy"   :{date.format}}:mmddyy;
-    {.ms "MM/dd/yyyy" :{date.format}}:mmddyyyy;
-    {.ms "hh:mm aa"   :{date.format}}:timestr;
+    {.ms "MM/dd/yy"   :(date.format)}:mmddyy;
+    {.ms "MM/dd/yyyy" :(date.format)}:mmddyyyy;
+    {.ms "hh:mm aa"   :(date.format)}:timestr;
 
 }:date;
 
diff --git a/std/dialog.aya b/std/dialog.aya
index 2c5fa81f..9c20e11c 100644
--- a/std/dialog.aya
+++ b/std/dialog.aya
@@ -1,11 +1,11 @@
 .# This file is a part of Aya: https://github.com/nick-paul/aya-lang
 
 .# dialog.aya
-.# Interface to the dialog operator :{dialog.legacy}
+.# Interface to the dialog operator :(dialog.legacy)
 
 .{? dialog
     various dialogs and windows
-    all functions in this module are shortcuts for the :{dialog.legacy} operator
+    all functions in this module are shortcuts for the :(dialog.legacy) operator
 .}
 
 module dialog
@@ -14,55 +14,55 @@ export ::dialog
 
 .#? ::str dialog.requeststr\n  request a string from the user
 def dialog::getstr {question,
-    question :{dialog.getstr}
+    question :(dialog.getstr)
 }
 
 .#? ::str dialog.requestnum\n  request a number from the user
 def dialog::getnum {question,
-    question :{dialog.getnum}
+    question :(dialog.getnum)
 }
 
 .#? ::str dialog.alert\n  display a dialog box with a given message
 def dialog::alert {text,
-    text "Aya" ::plain :{dialog.alert}
+    text "Aya" ::plain :(dialog.alert)
 }
 
 .#? ::str dialog.warning\n  display a warning message with the given message
 def dialog::warning {text,
-    text "Aya" ::warn :{dialog.alert}
+    text "Aya" ::warn :(dialog.alert)
 }
 
 .#? ::str dialog.error\n  display an error message with the given message
 def dialog::error {text,
-    text "Aya" ::error :{dialog.alert}
+    text "Aya" ::error :(dialog.alert)
 }
 
 .#? ::str dialog.warn\n  display a warning message with the given message
 def dialog::warn {text,
-    text "Aya" ::warn :{dialog.alert}
+    text "Aya" ::warn :(dialog.alert)
 }
 
 .#? ::str ::str ::str dialog.yesno\n  display a dialog box with the question ::str1. ::str2 and ::str3 return true and false respectively
 def dialog::yesno {question yes no,
-    question [yes no] "Aya" ::plain :{dialog.confirm}
+    question [yes no] "Aya" ::plain :(dialog.confirm)
 }
 
 .#? message::str dialog.confirm\n  Return 1 if the user presses okay and 0 otherwise
 def dialog::confirm {question,
-    question ["Okay" "Cancel"] "Aya" ::plain :{dialog.confirm}
+    question ["Okay" "Cancel"] "Aya" ::plain :(dialog.confirm)
 }
 
 .#? ::str ::list dialog.buttons\n  display a dialog box with buttons for each of the options in L. Returns the item in the list as a string.
 def dialog::buttons {question options::list,
-    question options "Aya" ::question :{dialog.buttons}
+    question options "Aya" ::question :(dialog.buttons)
 }
 
 .#? ::str ::list dialog.dropdown\n  display a dialog box with a dropdown selection of the options in L
 def dialog::dropdown {question options::list,
-    question options "Aya" ::question :{dialog.dropdown}
+    question options "Aya" ::question :(dialog.dropdown)
 }
 
 .#? dialog.choosefile\n  open a file selection window. return the full path of the selected file
 def dialog::choosefile {
-    :{dialog.choosefile}
+    :(dialog.choosefile)
 }
diff --git a/std/docstr.aya b/std/docstr.aya
index e3649fad..b25e5906 100644
--- a/std/docstr.aya
+++ b/std/docstr.aya
@@ -97,7 +97,7 @@ def (docstr.arg)::show {margin self : n l pad,
     }W.trim + pad \+
 }
 
-def docstr::_parseargs {self : matcher("(?m)^(:{2}|)[a-z]+:"),
+def docstr::_parseargs {self : matcher("(?m)^(:(2)|)[a-z]+:"),
     .# Names
     self.sections.args matcher & :#{B;}
     .# Desc
diff --git a/std/golf.aya b/std/golf.aya
index ed0655f5..30721c33 100644
--- a/std/golf.aya
+++ b/std/golf.aya
@@ -6,7 +6,7 @@
 exportall
 
 .# Import standard library
-:{sys.ad} "/std"+ :{sys.readdir}:# {".aya" S W :S} :# {name,
+:(sys.ad) "/std"+ :(sys.readdir):# {".aya" S W :S} :# {name,
     name ::golf = ! {
         import name
     } ?
diff --git a/std/image.aya b/std/image.aya
index a2185287..b74feca4 100644
--- a/std/image.aya
+++ b/std/image.aya
@@ -16,7 +16,7 @@ def image::__init__ {r g b a width height meta self,
 }
 
 def image::read {filename cls : img image^ path^,
-    filename :{image.read} :img;
+    filename :(image.read) :img;
     img.r img.g img.b img.a img.width img.height img.meta image!
 }
 
@@ -25,7 +25,7 @@ def image::__repr__ {self,
 }
 
 def image::write {filename self : path^,
-    self filename :{image.write}
+    self filename :(image.write)
 }
 
 def image::pixels {self,
diff --git a/std/io.aya b/std/io.aya
index bde175c5..cb9d3ae7 100644
--- a/std/io.aya
+++ b/std/io.aya
@@ -78,17 +78,17 @@ def path::__dec__ {self,
 
 .#? ::str path.readdir\n  list of file/dir names in the given path
 def path::readdir {path,
-    P :{sys.readdir}
+    P :(sys.readdir)
 }
 
 .#? path.working\n  working directory
 def path::working {path,
-    :{sys.wd} path!
+    :(sys.wd) path!
 }
 
 .#? path.aya\n  aya directory
 def path::aya {path,
-    :{sys.ad} path!
+    :(sys.ad) path!
 }
 
 def path::clean {self,
@@ -168,13 +168,13 @@ def path::_iswindows {self,
 .#
 
 .#? path.root\n  root dir name
-"user.dir" :{sys.getprop} :9s .^ S .[0] path.:root;
+"user.dir" :(sys.getprop) :9s .^ S .[0] path.:root;
 
 
 
-"~" :{sys.resolvehome} path! path.:home;
+"~" :(sys.resolvehome) path! path.:home;
 
-{, :{sys.wd} path._split :dirs} path :M path.:dfltworking;
+{, :(sys.wd) path._split :dirs} path :M path.:dfltworking;
 
 
 
@@ -188,63 +188,63 @@ def file::__init__ {filepath type::char  self : path^,
     .# save a copy of the path
     filepath path!      self.:path ;
     .# open the stream
-    self.path P type :{fstream.O} self.:id ;
+    self.path P type :(fstream.O) self.:id ;
 }
 
 .#? ::file.close\n  close a file. return 1 is success
 def file::close {self,
     self.flush;
-    self.id 'c :{fstream.O}
+    self.id 'c :(fstream.O)
 }
 
 .#? ::file.isopen\n  test if a file stream is open
 def file::isopen {self,
-    self.id 'i :{fstream.O} 0 =!
+    self.id 'i :(fstream.O) 0 =!
 }
 
 .#? ::file.isread\n  return 1 if file is an input stream
 def file::isinput {self,
-    self.id 'i :{fstream.O} 1 =
+    self.id 'i :(fstream.O) 1 =
 }
 
 .#? ::file.iswrite\n  return 1 if file is an output stream
 def file::isoutput {self,
-    self.id 'i :{fstream.O} 2 =
+    self.id 'i :(fstream.O) 2 =
 }
 
 .#? ::file.print\n  print to a file if it is an input stream
 def file::print {s self,
-    sP self.id :{fstream.O}
+    sP self.id :(fstream.O)
 }
 
 .#? ::file.println\n  print string followed by a newline tp a file
 def file::println {s self,
-    sP "\n" + self.id :{fstream.O}
+    sP "\n" + self.id :(fstream.O)
 }
 
 .#? ::file.readchar\n  read the next char in the file, return -1 if EOF or invalid stream
 def file::readchar {self,
-    self.id 'b :{fstream.O}
+    self.id 'b :(fstream.O)
 }
 
 .#? ::file.readline\n  read the next line in the file, return 0 is EOF or invalid stream
 def file::readline {self,
-    self.id 'l :{fstream.O}
+    self.id 'l :(fstream.O)
 }
 
 .#? ::file.readall\n  read all text in the stream, return "" if EOF and 0 if invalid stream
 def file::readall {self,
-    self.id 'a :{fstream.O}
+    self.id 'a :(fstream.O)
 }
 
 .#? ::file.lines\n  return a list containing the lines in the file
 def file::lines {self,
-    self.id 'a :{fstream.O} '\n' S
+    self.id 'a :(fstream.O) '\n' S
 }
 
 .#? ::file.flush\n  flush an output stream
 def file::flush {self,
-    self.id 'f :{fstream.O}
+    self.id 'f :(fstream.O)
 }
 
 def file::__repr__ {self,
@@ -328,7 +328,7 @@ dummyfile file.:dummyfile ;
 
 {,
     {path, .# ::path or ::str
-        path P :{fileutils.readallbytes}
+        path P :(fileutils.readallbytes)
     }:readallbytes;
 
 }:fileutils;
diff --git a/std/json.aya b/std/json.aya
index 2a45fa98..8398d2be 100644
--- a/std/json.aya
+++ b/std/json.aya
@@ -3,9 +3,9 @@ import ::io
 module json
 export ::json
 
-def json::loads {:{json.loads}}
+def json::loads {:(json.loads)}
 
-def json::dumps {:{json.dumps}}
+def json::dumps {:(json.dumps)}
 
 def json::load {json_file : file^ json^,
     json_file :T ::str = {
diff --git a/std/la.aya b/std/la.aya
index 23180aa2..c1595569 100644
--- a/std/la.aya
+++ b/std/la.aya
@@ -4,4 +4,4 @@
 .# Defines linear algebra functions
 
 .# Wrapper functions
-{:{la.mul}}:dot;
+{:(la.mul)}:dot;
diff --git a/std/matrix.aya b/std/matrix.aya
index 235191e7..b5fb2956 100644
--- a/std/matrix.aya
+++ b/std/matrix.aya
@@ -94,7 +94,7 @@ def matrix::__rmul__ {self n::num,
 }
 
 def matrix::matmul {other self, 
-    other.rows self.rows :{la.mul} self.M._new
+    other.rows self.rows :(la.mul) self.M._new
 }
 
 def matrix ::__add__ { other self,
diff --git a/std/plot.aya b/std/plot.aya
index 6ce12ea4..283e988b 100644
--- a/std/plot.aya
+++ b/std/plot.aya
@@ -83,7 +83,7 @@ def plot::scatter {x::list y params::dict self : dataset^ d,
 def plot::view {self,
     self.M._supress_windows ! {
         "" self.:filename;
-        self :{plot.plot}
+        self :(plot.plot)
     } ?
 
 }
@@ -105,7 +105,7 @@ def multiplot::add {plot self,
 def multiplot::view {self : plot^,
     plot._supress_windows ! {
         "" self.:filename;
-        self :{plot.multiplot}
+        self :(plot.multiplot)
     } ?
 }
 
diff --git a/std/shell.aya b/std/shell.aya
index f3e3dd7e..73444255 100644
--- a/std/shell.aya
+++ b/std/shell.aya
@@ -33,7 +33,7 @@ def shell_impl::echo {data::str : shellresult^ ,
 
 .#? ls\n  print a list of files in the working dir
 def ::ls {: shellresult^ ,
-    :{sys.wd} :{sys.readdir}
+    :(sys.wd) :(sys.readdir)
     .E 0 = {
         ; "  "
     } {
diff --git a/std/socket.aya b/std/socket.aya
index b2edc61c..b166a18b 100644
--- a/std/socket.aya
+++ b/std/socket.aya
@@ -14,49 +14,49 @@ struct socket_server {
 }
 
 def socket_server::accept {self : socket^,
-    self._srv :{socket.accept} socket!
+    self._srv :(socket.accept) socket!
 }
 
 def socket_server::listen {addr port : socket_server^,
-    addr port :{socket.open_server} socket_server!
+    addr port :(socket.open_server) socket_server!
 }
 
 def socket_server::close {self,
-    self._srv :{socket.close}
+    self._srv :(socket.close)
 }
 
 def socket_server::port {self,
-    self._srv :{socket.get_port}
+    self._srv :(socket.get_port)
 }
 
 def socket_server::addr {self,
-    self._srv :{socket.get_addr}
+    self._srv :(socket.get_addr)
 }
 
 def socket::connect {addr port : socket^,
-    addr port :{socket.open_client} socket!
+    addr port :(socket.open_client) socket!
 }
 
 def socket::recv {self,
-    self._sock :{socket.recv}
+    self._sock :(socket.recv)
 }
 
 def socket::port {self,
-    self._sock :{socket.get_port}
+    self._sock :(socket.get_port)
 }
 
 def socket::addr {self,
-    self._sock :{socket.get_addr}
+    self._sock :(socket.get_addr)
 }
 
 def socket::send {self,
-    self._sock :{socket.send}
+    self._sock :(socket.send)
 }
 
 def socket::println {data self,
-    data P "\r\n" + self._sock :{socket.send}
+    data P "\r\n" + self._sock :(socket.send)
 }
 
 def socket::close {self,
-    self._sock :{socket.close}
+    self._sock :(socket.close)
 }
diff --git a/std/sys.aya b/std/sys.aya
index 74a72c59..779d7128 100644
--- a/std/sys.aya
+++ b/std/sys.aya
@@ -3,7 +3,7 @@ from ::io import ::path
 module sys
 export ::sys
 
-def sys::args :{sys.args}
+def sys::args :(sys.args)
 
 
 .#? sys.iswindows\n  returns true if system is windows
@@ -15,19 +15,19 @@ def sys::cd {dirname : path^,
     dirname
     .# If it is a string, conv to path
     dirname :T ::str = { path! } ?
-    P :{sys.cd}
+    P :(sys.cd)
 }
 
 
 .#? ::str sys.mkdir\n  create a new directory
 def sys::mkdir {dir,
-    dir P :{sys.mkdir}
+    dir P :(sys.mkdir)
 }
 
 
 def sys::readdir {dir,
     dir P :dir;
     dir "" = {"." :dir;} ?
-    dir :{sys.readdir}
+    dir :(sys.readdir)
 }
 
diff --git a/std/terminal.aya b/std/terminal.aya
index fcbbcc6a..113ebada 100644
--- a/std/terminal.aya
+++ b/std/terminal.aya
@@ -43,7 +43,7 @@ def terminal::replcolor {c::color : color^ terminal^ ,
     [c terminal._setfgstr
      "aya> "
      color.colors.white terminal._setfgstr]W
-    :{sys.alterprompt}
+    :(sys.alterprompt)
 }
 
 def terminal::print_color {value c::color : terminal^ prev_fg,
diff --git a/std/threading.aya b/std/threading.aya
index b8219064..fc41c72f 100644
--- a/std/threading.aya
+++ b/std/threading.aya
@@ -1,12 +1,12 @@
 struct thread {id}
 
 def ::new {: thread^,
-    :{thread.new} thread!
+    :(thread.new) thread!
 }
 
 .# Create a new thread
 def thread::new {cls,
-    :{thread.new} thread!
+    :(thread.new) thread!
 }
 
 
@@ -16,7 +16,7 @@ def thread::add_task {block self,
     .# aya> {1 1 +} thread.add_task
     .# aya> {1 1 +} thread +
 
-    block.` self.id :{thread.add_task}
+    block.` self.id :(thread.add_task)
     self
 }
 
@@ -34,14 +34,14 @@ def thread::wait_for_result {self,
     .#
     .# aya> thread.wait_for_result
     .# aya> thread .|
-    self.id :{thread.wait_for_result}
+    self.id :(thread.wait_for_result)
 }
 
 def thread::__abs__ (thread.wait_for_result.`)
 
 
 def thread::has_unfinished_tasks {self,
-    self.id :{thread.has_unfinished_tasks}
+    self.id :(thread.has_unfinished_tasks)
 }
 
 
diff --git a/test/examples.aya b/test/examples.aya
index 56b36aab..82505e84 100644
--- a/test/examples.aya
+++ b/test/examples.aya
@@ -45,7 +45,7 @@ import ::plot
 "plot/weierstrass"
 ] :# {ex, 
     "\n## $ex:" :P
-    [ "$(:{sys.ad})/examples/$ex.aya" :F ];
+    [ "$(:(sys.ad))/examples/$ex.aya" :F ];
 } ;
 
 .# Revert supress windows
diff --git a/test/filesystem.aya b/test/filesystem.aya
index 599cae15..de36d1ea 100644
--- a/test/filesystem.aya
+++ b/test/filesystem.aya
@@ -11,75 +11,75 @@ import ::image
 {path::str, path :9s + } :sep;
 
 .# Create a directory
-"dir1" :{sys.mkdir}
-{"." :{sys.readdir} ["dir1"sep] = 1} test.test
+"dir1" :(sys.mkdir)
+{"." :(sys.readdir) ["dir1"sep] = 1} test.test
 
 .# Change working directory
-"dir1" :{sys.cd}
-"dir2" :{sys.mkdir}
-{"." :{sys.readdir} ["dir2"sep] = 1} test.test
+"dir1" :(sys.cd)
+"dir2" :(sys.mkdir)
+{"." :(sys.readdir) ["dir2"sep] = 1} test.test
 
-".." :{sys.cd}
-{"." :{sys.readdir} ["dir1"sep] = 1} test.test
+".." :(sys.cd)
+{"." :(sys.readdir) ["dir1"sep] = 1} test.test
 
-"../../" :{sys.set_ad}
-"../" :{sys.cd}
-{"fs_test" :{sys.readdir} ["dir1"sep] = 1} test.test
+"../../" :(sys.set_ad)
+"../" :(sys.cd)
+{"fs_test" :(sys.readdir) ["dir1"sep] = 1} test.test
 
 .# Set aya dir back to normal
-"." :{sys.set_ad}
-"fs_test" :{sys.cd}
-{"." :{sys.readdir} ["dir1"sep] = 1} test.test
-"dir1" :{sys.cd}
-{"." :{sys.readdir} ["dir2"sep] = 1} test.test
+"." :(sys.set_ad)
+"fs_test" :(sys.cd)
+{"." :(sys.readdir) ["dir1"sep] = 1} test.test
+"dir1" :(sys.cd)
+{"." :(sys.readdir) ["dir2"sep] = 1} test.test
 
 .# Return to aya dir
-"" :{sys.cd}
+"" :(sys.cd)
 .# Go into fs_test dir
-"fs_test" :{sys.cd}
-{"." :{sys.readdir} ["dir1"sep] = 1} test.test
+"fs_test" :(sys.cd)
+{"." :(sys.readdir) ["dir1"sep] = 1} test.test
 
 .# cd into nested directory
-"dir1/dir2/" :{sys.cd}
-{"." :{sys.readdir} [] = 1} test.test
-"../.." :{sys.cd}
-{"." :{sys.readdir} ["dir1"sep] = 1} test.test
+"dir1/dir2/" :(sys.cd)
+{"." :(sys.readdir) [] = 1} test.test
+"../.." :(sys.cd)
+{"." :(sys.readdir) ["dir1"sep] = 1} test.test
 
 
 .# Write a file
-"hello.txt" 'w :{fstream.O} :id;
-{"Hello!" id :{fstream.O} 1} test.test
-{id 'c :{fstream.O} 1} test.test
+"hello.txt" 'w :(fstream.O) :id;
+{"Hello!" id :(fstream.O) 1} test.test
+{id 'c :(fstream.O) 1} test.test
 .# Use C to sort lists when checking if they are equal
-{"." :{sys.readdir}C ["dir1"sep "hello.txt"]C = 1} test.test
+{"." :(sys.readdir)C ["dir1"sep "hello.txt"]C = 1} test.test
 
 .# Read a file
-"hello.txt" 'r :{fstream.O} :id;
-{id 'a :{fstream.O} "Hello!"} test.test
-{id 'c :{fstream.O} 1} test.test
+"hello.txt" 'r :(fstream.O) :id;
+{id 'a :(fstream.O) "Hello!"} test.test
+{id 'c :(fstream.O) 1} test.test
 
 
 .# Write a file in a directory
-"dir1/two-plus-two.txt" 'w :{fstream.O} :id;
-{"four" id :{fstream.O} 1} test.test
-{id 'c :{fstream.O} 1} test.test
+"dir1/two-plus-two.txt" 'w :(fstream.O) :id;
+{"four" id :(fstream.O) 1} test.test
+{id 'c :(fstream.O) 1} test.test
 .# Use C to sort lists when checking if they are equal
-{"." :{sys.readdir}C ["dir1"sep "hello.txt"]C = 1} test.test
-{"dir1/" :{sys.readdir}C ["dir2"sep "two-plus-two.txt"]C = 1} test.test
+{"." :(sys.readdir)C ["dir1"sep "hello.txt"]C = 1} test.test
+{"dir1/" :(sys.readdir)C ["dir2"sep "two-plus-two.txt"]C = 1} test.test
 
 .# Read a file in a directory
-"dir1/two-plus-two.txt" 'r :{fstream.O} :id;
-{id 'a :{fstream.O} "four"} test.test
-{id 'c :{fstream.O} 1} test.test
+"dir1/two-plus-two.txt" 'r :(fstream.O) :id;
+{id 'a :(fstream.O) "four"} test.test
+{id 'c :(fstream.O) 1} test.test
 
 .# Create a directory in a directory
-"dir1/dir2/dir3" :{sys.mkdir}
-{"dir1/dir2" :{sys.readdir} ["dir3"sep] = 1} test.test
+"dir1/dir2/dir3" :(sys.mkdir)
+{"dir1/dir2" :(sys.readdir) ["dir3"sep] = 1} test.test
 
 .# Create a single pixel image
 {, 1:width 1:height [41]:r [164]:g [34]:b }:img;
-img "out.png" :{image.write}
-{"." :{sys.readdir}C ["dir1"sep "hello.txt" "out.png"]C = 1} test.test
+img "out.png" :(image.write)
+{"." :(sys.readdir)C ["dir1"sep "hello.txt" "out.png"]C = 1} test.test
 
 .# Read an image
 "out.png" image.read :img;
diff --git a/test/test.aya b/test/test.aya
index 73f8094c..4b45dc53 100644
--- a/test/test.aya
+++ b/test/test.aya
@@ -21,7 +21,7 @@
 {fname,
     {, 
     "* Running tests '$fname'..." :P
-    "$(:{sys.ad})$fname.aya" :F
+    "$(:(sys.ad))$fname.aya" :F
     "  Tests complete: '$fname'" :P
     };
 }:load_test;
@@ -66,7 +66,7 @@
 
 .# Import entire standard library
 "Importing standard library..." :P
-:{sys.ad} "/std"+ :{sys.readdir}:# {".aya".^ S W} :# {name, "importing $name...":P import name} ;
+:(sys.ad) "/std"+ :(sys.readdir):# {".aya".^ S W} :# {name, "importing $name...":P import name} ;
 "Import finished!" :P
 "":P
 

From 38ea07ebd6d987d6d93f0312837ad7dbbfcb32c2 Mon Sep 17 00:00:00 2001
From: npgit 
Date: Tue, 17 Dec 2024 18:14:21 -0500
Subject: [PATCH 2/3] Switch dict syntax from '{, ...}' to ':{...}'

---
 README.md                                     |  8 +--
 base/__aya__.aya                              | 38 +++++-----
 base/block.aya                                |  8 +--
 base/char.aya                                 |  2 +-
 base/importlib.aya                            |  8 +--
 base/list.aya                                 |  4 +-
 base/num.aya                                  |  2 +-
 base/str.aya                                  |  2 +-
 base/sym.aya                                  |  6 +-
 base/test.aya                                 |  2 +-
 examples/canvas/attractor.aya                 |  2 +-
 examples/canvas/boids.aya                     |  2 +-
 examples/canvas/bouncing.aya                  |  2 +-
 examples/canvas/color_table.aya               |  2 +-
 examples/canvas/color_typewriter.aya          |  2 +-
 examples/canvas/cube.aya                      |  2 +-
 examples/canvas/graphics.aya                  |  6 +-
 examples/canvas/julia.aya                     |  6 +-
 examples/canvas/logo.aya                      |  2 +-
 examples/canvas/mouse.aya                     |  2 +-
 examples/canvas/particles.aya                 |  2 +-
 examples/canvas/vaporwave_city.aya            |  2 +-
 examples/defaultdict.aya                      |  2 +-
 examples/list_iterator.aya                    |  6 +-
 examples/package_aya_libs.aya                 |  2 +-
 examples/plot/bernstein.aya                   |  2 +-
 examples/plot/betting.aya                     |  2 +-
 examples/plot/box_plot.aya                    | 30 ++++----
 examples/plot/canvas_multiplot.aya            | 34 ++++-----
 examples/plot/iris.aya                        |  4 +-
 examples/plot/lakehuron.aya                   |  6 +-
 examples/plot/multi.aya                       |  6 +-
 examples/plot/normal.aya                      |  2 +-
 examples/plot/numdx.aya                       |  8 +--
 examples/plot/pie_chart.aya                   | 10 +--
 examples/plot/rainbow.aya                     |  2 +-
 examples/plot/randomwalk.aya                  |  2 +-
 examples/plot/scatter.aya                     |  2 +-
 examples/plot/simple_functions.aya            |  8 +--
 examples/plot/sinsrs.aya                      |  2 +-
 examples/plot/weierstrass.aya                 |  2 +-
 examples/quicksort.aya                        |  2 +-
 examples/rdatasets.aya                        |  2 +-
 examples/setindex.aya                         |  8 +--
 examples/singleton.aya                        |  2 +-
 examples/syntax.aya                           |  4 +-
 examples/turtle/flower.aya                    |  2 +-
 examples/turtle/random.aya                    |  4 +-
 examples/turtle/snowflake.aya                 |  2 +-
 examples/turtle/square.aya                    |  2 +-
 manual/blocks_and_functions.md                | 12 ++--
 manual/dictionaries.md                        | 32 ++++-----
 manual/multithreading.md                      |  6 +-
 manual/standard_library.md                    |  6 +-
 manual/syntax_overview.md                     | 44 ++++++------
 manual/tour.md                                | 14 ++--
 manual/user_types.md                          |  6 +-
 src/aya/TypeIDs.java                          |  3 +
 src/aya/ext/image/AyaImage.java               |  4 +-
 .../plot/instruction/PieChartInstruction.java |  4 +-
 .../instruction/DictLiteralInstruction.java   |  2 +-
 .../EmptyDictLiteralInstruction.java          |  2 +-
 src/aya/instruction/op/Operator.java          |  2 +-
 src/aya/obj/dict/Dict.java                    |  8 +--
 src/aya/parser/Parser.java                    | 27 ++++++-
 src/aya/parser/tokens/BlockToken.java         | 18 ++---
 src/aya/parser/tokens/DictToken.java          | 71 +++++++++++++++++++
 src/aya/parser/tokens/Token.java              |  3 +
 std/bitset.aya                                |  4 +-
 std/canvas.aya                                | 22 +++---
 std/color.aya                                 |  2 +-
 std/csv.aya                                   |  4 +-
 std/dataframe.aya                             |  8 +--
 std/date.aya                                  | 22 +++---
 std/docs.aya                                  |  2 +-
 std/docstr.aya                                | 14 ++--
 std/enum.aya                                  |  8 +--
 std/golf.aya                                  |  4 +-
 std/io.aya                                    | 10 +--
 std/map.aya                                   |  4 +-
 std/math.aya                                  |  2 +-
 std/matrix.aya                                |  8 +--
 std/missing.aya                               |  2 +-
 std/plot.aya                                  | 12 ++--
 std/rdatasets.aya                             |  6 +-
 std/shell.aya                                 |  2 +-
 std/turtle.aya                                |  8 +--
 std/unit.aya                                  |  4 +-
 std/viewmat.aya                               |  2 +-
 test/base/test_block.aya                      |  6 +-
 test/base/test_list.aya                       |  4 +-
 test/colon_ops.aya                            |  6 +-
 test/core.aya                                 | 54 +++++++-------
 test/dot_ops.aya                              |  8 +--
 test/filesystem.aya                           |  2 +-
 test/std/test_matrix.aya                      |  2 +-
 test/test.aya                                 |  4 +-
 test/test_op_overload.aya                     | 60 ++++++++--------
 test/unicode.aya                              | 10 +--
 99 files changed, 471 insertions(+), 371 deletions(-)
 create mode 100644 src/aya/parser/tokens/DictToken.java

diff --git a/README.md b/README.md
index c484ac78..a3676df3 100644
--- a/README.md
+++ b/README.md
@@ -195,7 +195,7 @@ Use aya's `turtle` and `color` modules to draw a pattern
 import ::turtle
 import ::color
 
-{,
+:{
     400:width;
     400:height;
     color.colors.darkblue :bg_color;
@@ -225,7 +225,7 @@ import ::plot
 import ::stats
 
 "Downloading file..." :P
-{,
+:{
     "https://raw.githubusercontent.com/vincentarelbundock/Rdatasets/master/csv/datasets/LakeHuron.csv":filename
     1:csvindex
 }
@@ -238,8 +238,8 @@ df.["value"] :y;
 x y stats.regression :r;
 
 plot.plot! :plt;
-x y   {, "Water Level":label} plt.plot
-x {r} {, "Trend":label} plt.plot
+x y   :{ "Water Level":label} plt.plot
+x {r} :{ "Trend":label} plt.plot
 
 "Water Level of Lake Huron" plt.:title;
 [575 583] plt.y.:lim;
diff --git a/base/__aya__.aya b/base/__aya__.aya
index 15daa3d3..22ef79ac 100644
--- a/base/__aya__.aya
+++ b/base/__aya__.aya
@@ -10,9 +10,9 @@
 {:(sys.ad) "test/test.aya" + :F}:tt;
 
 .# Global __aya__ table
-{,
+:{
 
-    {,}:interpreter;
+    :{}:interpreter;
 
     .# If set to 1, all breakpoints will be ignored
     .#? __aya__.ignore_breakpoints\n  if true, skip all breakpoints
@@ -20,8 +20,8 @@
 
 }:__aya__;
 
-{,
-    {, 
+:{
+    :{ 
         ::__nil :__type__;
         "nil" :__str__;
         "nil" :__repr__'
@@ -91,9 +91,9 @@
         }
     )
 
-    aya> f {,} ::foo {"a"}
+    aya> f :{} ::foo {"a"}
     with_mod!
-    [ {"a"} ::foo {,} ]
+    [ {"a"} ::foo :{} ]
 
     aya> f ::foo {"a"}
     no mod!
@@ -109,7 +109,7 @@
         _no_mod:no_mod;
 
         .# Store functions on stack so they can be retrieved later
-        {,
+        :{
             no_mod.` :no_mod
             with_mod.` :with_mod
         }
@@ -119,8 +119,8 @@
             .# aya> {mod name block, mod ::_fn =! {;} ? [mod name block.`]} :f
 
             .# Jump ahead 3 items
-            .# aya> (```(\:&:T ::sym=! {\`}{\}.? f) ::_fn)   {,} ::foo {+}
-            .# [ {,} ::foo {+} ]
+            .# aya> (```(\:&:T ::sym=! {\`}{\}.? f) ::_fn)   :{} ::foo {+}
+            .# [ :{} ::foo {+} ]
 
             .# Jump ahead 2 items
             .# aya> (```(\:&:T ::sym=! {\`}{\}.? f) ::_fn)   ::foo {+}
@@ -156,7 +156,7 @@
     }
 
     .# Use constant substitution until var^ syntax is introduced
-    {, no_mod.`:_no_mod with_mod.`:_with_mod} .+
+    :{ no_mod.`:_no_mod with_mod.`:_with_mod} .+
 
 } __aya__.:opt_mod;
 
@@ -178,7 +178,7 @@
 
     Define a function in a module scope:
 
-        aya> {,}:math;
+        aya> :{}:math;
         aya> def math::sq {2^}
         aya> 5 math.sq
         25
@@ -194,7 +194,7 @@
 
     Define a function in a submodule:
 
-        aya> {, {,}:stats; }:math;
+        aya> :{ :{}:stats; }:math;
         aya> def (math.stats)::mean {.E\W\/}
         aya> [1 2 3 4] math.stats.mean
         2.5
@@ -218,9 +218,9 @@
 .#
 .# `objcet`: Base object for class and struct
 .#
-{,
+:{
     {meta : instance,
-        {,
+        :{
             meta :__meta__;
             1 :__pushself__;
         } :instance;
@@ -250,7 +250,7 @@
 .#
 
 {type::sym super,
-    {,
+    :{
         super:__meta__;
         type:__type__;
         .# copy new from super directly
@@ -297,7 +297,7 @@ __aya__.extend.` :extend;
         num_members :A
         .# and assign them to self
         members {self :D} .&;
-    } {,
+    } :{
         members__ E :num_members;
         members__   :members;
     } .+ cls__.:__init__;
@@ -311,7 +311,7 @@ __aya__.extend.` :extend;
         " ) " +
         name  +
         "!"+
-    } {,
+    } :{
         type__ :C   :name;
         members__ :members;
     } .+ cls__.:__str__;
@@ -332,14 +332,14 @@ __aya__.extend.` :extend;
 
 .#? module sym\n  declare a new module
 {name::sym,
-    {,
+    :{
         name :__modname__;
 
         {meta,
             "Cannot create new instance of module $(meta.__modname__:C)" .D
         } :__new__;
 
-        {,
+        :{
             ::module :__type__;
             "(module $name)":__repr__;
         }:__meta__;
diff --git a/base/block.aya b/base/block.aya
index 23f2ee2c..7d0c85d8 100644
--- a/base/block.aya
+++ b/base/block.aya
@@ -1,4 +1,4 @@
-{,
+:{
 
     .# Functional Operations
     .########################
@@ -60,7 +60,7 @@
     .}
     {(1 hold)({:d__,
         .# Create a dictionary of all values given by the list
-        {,}:d__;
+        :{}:d__;
         :#{$~\d__:D;};
         .# Substitute the values from the dictionary into the block
         d__ .+
@@ -78,14 +78,14 @@
         aya> {1 +}:a 2:b
         {1 +} 2
         aya> [::a ::b].capture_vars
-        {,
+        :{
           {1 +}:a;
           2:b;
         }
         aya> [::a ::b ::c].capture_vars
         ERROR: Variable c not found
     .}
-    { {1, :# {$~\:=} } }:_capture_vars;
+    { :{1, :# {$~\:=} } }:_capture_vars;
 
 
     .#? ::block .op\n  return the block (allows use of (::sym or ::block) .op without type checking
diff --git a/base/char.aya b/base/char.aya
index 3f034fb9..48d0e1b0 100644
--- a/base/char.aya
+++ b/base/char.aya
@@ -2,7 +2,7 @@
 
 .# Metatable definition for the built-in `char` type
 
-{,
+:{
     .#? C.islower\n  tests if a character is lowercase
     {$ 'a :> \ 'z :< &}:islower;
 
diff --git a/base/importlib.aya b/base/importlib.aya
index d481c81a..c45e383b 100644
--- a/base/importlib.aya
+++ b/base/importlib.aya
@@ -9,7 +9,7 @@ def importlib::_log_debug {:importlib^,
 def importlib::aya_dir :(sys.ad)
 
 .# Dictionary of files which have been imported
-def importlib::imported {,}
+def importlib::imported :{}
 
 def importlib::path [
     importlib.aya_dir "std" :9s + +    .# /base
@@ -34,7 +34,7 @@ def importlib::load_file {filename : importlib^,
         { .# try
             "Attempting to open file $filename..." importlib._log_debug
             .# Load the file into a dict scope
-            {,
+            :{
                 .# If __main__ exists and is 0, `main` will discard its block
                 .# Otherwise it will execute it
                 0:__main__;
@@ -216,7 +216,7 @@ def importlib::export {vars : importlib^,
 def importlib::from {mod_sym import_vars : meta_mod importlib^,
     "$mod_sym $import_vars importlib.from" importlib._log_debug
     "from: Capturing all imported vars..." importlib._log_debug
-    {,
+    :{
         mod_sym importlib.import
     }:meta_mod;
 
@@ -245,7 +245,7 @@ importlib __aya__.:importlib;
 .# If provided a 0 (for example from `from` keyword), do nothing
 {(1 hold)(:& 0= {;} {__aya__.importlib.import} .?)}:import;
 
-{: importlib^ , {,} importlib.:imported; } :reimport;
+{: importlib^ , :{} importlib.:imported; } :reimport;
 
 {(1 hold)(__aya__.importlib.export)}:export;
 {1:__export__;} :exportall;
diff --git a/base/list.aya b/base/list.aya
index d07b6377..cdf07257 100644
--- a/base/list.aya
+++ b/base/list.aya
@@ -2,7 +2,7 @@
 
 .# Metatable definition for the built-in `list` type
 
-{,
+:{
     .# Querying
     .###############
 
@@ -152,7 +152,7 @@
 
     .#? ::list.dict_flatten\n  given a list of dicts, flatten the into a single dict
     {
-        {,}\J{.+}%
+        :{}\J{.+}%
     }:dict_flatten;
 
 
diff --git a/base/num.aya b/base/num.aya
index 4f3e593d..aca22299 100644
--- a/base/num.aya
+++ b/base/num.aya
@@ -2,7 +2,7 @@
 
 .# Metatable definition for the built-in `num` type
 
-{,
+:{
 
     .#? ::num .digits\n  convert a number into a list of digits
     {
diff --git a/base/str.aya b/base/str.aya
index abd69f83..b94f8600 100644
--- a/base/str.aya
+++ b/base/str.aya
@@ -3,7 +3,7 @@
 .# string.aya
 .# Defines functions for working with strings and regular expressions
 
-{,
+:{
     .# Import list variables
     [].M W
 
diff --git a/base/sym.aya b/base/sym.aya
index 3d603849..5faf6481 100644
--- a/base/sym.aya
+++ b/base/sym.aya
@@ -2,7 +2,7 @@
 
 .# Metatable definition for the built-in `sym` type
 
-{,
+:{
     .{? ::sym .op
 
         Return a block containing the operator
@@ -24,7 +24,7 @@
     }:op;
 
     .# Get a dict of all operator/symbol pairs
-    {,
+    :{
         "overloadable" M? :# {
             .# Get   as strings
             :& "overloadable:.*$" & .[0] " " S .[-1] \ " " S .[0]
@@ -54,7 +54,7 @@
         ::__radd__
     .}
 
-    {,
+    :{
         .# Get the overload list for all ops
         ::ops Ma :#{.overload}
         .# Get all ops with non-zero length overloads
diff --git a/base/test.aya b/base/test.aya
index f1f5aa40..623350ae 100644
--- a/base/test.aya
+++ b/base/test.aya
@@ -3,7 +3,7 @@
 .# test.aya
 .# Defines an interface for testing aya code
 
-{, } :test;
+:{ } :test;
 
 .# New simpler test function
 {blk,
diff --git a/examples/canvas/attractor.aya b/examples/canvas/attractor.aya
index 4712418f..10606dc0 100644
--- a/examples/canvas/attractor.aya
+++ b/examples/canvas/attractor.aya
@@ -59,7 +59,7 @@ def attractor::show {self,
 .# Run Loop
 .###########
 
-{, "Attractor":name 0:autoflush } canvas! :cvs;
+:{ "Attractor":name 0:autoflush } canvas! :cvs;
 
 .# Create list of movers
 [50,;
diff --git a/examples/canvas/boids.aya b/examples/canvas/boids.aya
index 13dfaa85..cae10931 100644
--- a/examples/canvas/boids.aya
+++ b/examples/canvas/boids.aya
@@ -7,7 +7,7 @@ import ::time
 500 :width;
 500 :height;
 
-{, width:width height:height "Boids":name } canvas! :c;
+:{ width:width height:height "Boids":name } canvas! :c;
 
 struct boid { pos vel acc }
 
diff --git a/examples/canvas/bouncing.aya b/examples/canvas/bouncing.aya
index 83835daa..116fc190 100644
--- a/examples/canvas/bouncing.aya
+++ b/examples/canvas/bouncing.aya
@@ -4,7 +4,7 @@ import ::time
 .# Initialize the canvas
 400:w;
 300:h;
-{, w:width h:height "Bouncing":name } canvas! :c;
+:{ w:width h:height "Bouncing":name } canvas! :c;
 
 
 30:rad;
diff --git a/examples/canvas/color_table.aya b/examples/canvas/color_table.aya
index 0c49b009..066e1682 100644
--- a/examples/canvas/color_table.aya
+++ b/examples/canvas/color_table.aya
@@ -2,7 +2,7 @@ import ::color
 import ::canvas
 
 {colors radius : cvs, 
-    {, colors :E radius *~ :height; :width;} canvas!:cvs;
+    :{ colors :E radius *~ :height; :width;} canvas!:cvs;
     colors.enumerate #{[x cols],
         cols.enumerate #{[y col],
             col cvs.set_color
diff --git a/examples/canvas/color_typewriter.aya b/examples/canvas/color_typewriter.aya
index d0fd69a9..7e33982d 100644
--- a/examples/canvas/color_typewriter.aya
+++ b/examples/canvas/color_typewriter.aya
@@ -12,7 +12,7 @@ import ::color
 color.colors.white num_tiles 2^ L :grid;
 0:index;
 
-{,
+:{
     num_tiles :width
     num_tiles :height
     tile_width :scale
diff --git a/examples/canvas/cube.aya b/examples/canvas/cube.aya
index 27c3a738..e4765f70 100644
--- a/examples/canvas/cube.aya
+++ b/examples/canvas/cube.aya
@@ -11,7 +11,7 @@ color.colors.black :black;
 color.colors.white :white;
 
 .# Create a new canvas
-{, "3D Cube":name 0:autoflush } canvas! :c;
+:{ "3D Cube":name 0:autoflush } canvas! :c;
 2 c.set_stroke_width
 
 0 :theta;
diff --git a/examples/canvas/graphics.aya b/examples/canvas/graphics.aya
index 625d5510..8ea410af 100644
--- a/examples/canvas/graphics.aya
+++ b/examples/canvas/graphics.aya
@@ -6,15 +6,15 @@
 .}
 
 
-{,255Q:r 255Q:g 255Q:b}:col;
-{,100:r 100:g 100:b}:col;
+:{255Q:r 255Q:g 255Q:b}:col;
+:{100:r 100:g 100:b}:col;
 {x y,
     1 g :(graphics.set_stroke_width)
     0 0 0 g :(graphics.set_color)
     x y x y g :(graphics.line)
 }:point;
 
-{, 300:width 300:height "Test":name 1:autoflush 1:show} :(graphics.new) :g;
+:{ 300:width 300:height "Test":name 1:autoflush 1:show} :(graphics.new) :g;
 200 200 point
 0 0 100 200 g :(graphics.line)
 150 0 150 300 g :(graphics.line)
diff --git a/examples/canvas/julia.aya b/examples/canvas/julia.aya
index 6094ec4b..4bb90532 100644
--- a/examples/canvas/julia.aya
+++ b/examples/canvas/julia.aya
@@ -47,8 +47,8 @@ def ::julia { kwargs :
     div_time
 }
 
-{,} julia 4 viewmat_scaled.show
+:{} julia 4 viewmat_scaled.show
 
 .# Higher resolution; may take ~20 seconds
-.# {, 400:width 360:height 130:max_iterations } julia viewmat.show
-.# {, 400:width 360:height 250:max_iterations :-0.7269i0.1889:c } julia viewmat.show
+.# :{ 400:width 360:height 130:max_iterations } julia viewmat.show
+.# :{ 400:width 360:height 250:max_iterations :-0.7269i0.1889:c } julia viewmat.show
diff --git a/examples/canvas/logo.aya b/examples/canvas/logo.aya
index f2b4c838..29b3555a 100644
--- a/examples/canvas/logo.aya
+++ b/examples/canvas/logo.aya
@@ -2,7 +2,7 @@ import ::canvas
 
 
 300 :width;
-{,
+:{
   1:show
   1:autoflush
   width:width
diff --git a/examples/canvas/mouse.aya b/examples/canvas/mouse.aya
index 75727e3c..fe4d87fa 100644
--- a/examples/canvas/mouse.aya
+++ b/examples/canvas/mouse.aya
@@ -3,7 +3,7 @@ import ::time
 
 .# A simple mouse input example
 
-{,} canvas! :cvs;
+:{} canvas! :cvs;
 cvs.show
 
 60 time.rate! :limiter;
diff --git a/examples/canvas/particles.aya b/examples/canvas/particles.aya
index c7780c16..2bbcff32 100644
--- a/examples/canvas/particles.aya
+++ b/examples/canvas/particles.aya
@@ -49,7 +49,7 @@ def particle::dead {self,
 
 
 .# Create a new canvas
-{, "Particles":name 0:autoflush } canvas! :c;
+:{ "Particles":name 0:autoflush } canvas! :c;
 .# The spawn location of the particles
 [200 100] :origin;
 .# Array of particles
diff --git a/examples/canvas/vaporwave_city.aya b/examples/canvas/vaporwave_city.aya
index 9dfe3c0a..eb59df62 100644
--- a/examples/canvas/vaporwave_city.aya
+++ b/examples/canvas/vaporwave_city.aya
@@ -7,7 +7,7 @@ import ::color
 300:h;
 
 .# Create a new canvas
-{,
+:{
     "Vaporwave City":name
     w:width
     h:height
diff --git a/examples/defaultdict.aya b/examples/defaultdict.aya
index 2962ee12..087df308 100644
--- a/examples/defaultdict.aya
+++ b/examples/defaultdict.aya
@@ -27,7 +27,7 @@ def defaultdict::__str__ {self,
 def defaultdict::__repr__ (defaultdict.__str__.`)
 
 .# Create a default dict
-{,} 0 defaultdict! :dd;
+:{} 0 defaultdict! :dd;
 "> Dict is $dd" :P
 
 "> Adding x=10..." :P
diff --git a/examples/list_iterator.aya b/examples/list_iterator.aya
index 7a1b3873..6bbe85b5 100644
--- a/examples/list_iterator.aya
+++ b/examples/list_iterator.aya
@@ -2,7 +2,7 @@ import ::iterator
 
 .# Implementing and using an iterator
 
-{,
+:{
   .# Any user types must define a "type"
   .# "type" should always be a symbol
   .#   representation of the type name
@@ -15,12 +15,12 @@ import ::iterator
   .# `mylist` is just a wrapper for a list
   .#   we assign the list variable to `.l`
   {l,
-    {,l:l} mylist MO
+    :{l:l} mylist MO
   }:new;
 
   .# All types that implement iterator must
   .#   must define an `iter` dict
-  {,
+  :{
     .# since mylist is just a list wrapper,
     .#   we can use the built in listiter
     .#   to define `start`, `next`, and `done`
diff --git a/examples/package_aya_libs.aya b/examples/package_aya_libs.aya
index ebeb8767..fadf6de0 100644
--- a/examples/package_aya_libs.aya
+++ b/examples/package_aya_libs.aya
@@ -11,7 +11,7 @@ import ::io
 .# Convert to strings
 files #P :files;
 
-{,} :data;
+:{} :data;
 
 files :# {file,
     file G data.:[file];
diff --git a/examples/plot/bernstein.aya b/examples/plot/bernstein.aya
index 21b35dfc..31894712 100644
--- a/examples/plot/bernstein.aya
+++ b/examples/plot/bernstein.aya
@@ -14,7 +14,7 @@ plot.plot! :plt;
 
 .# generate polynomials
 coeff B .R # {i : f,
-  x ({a coeff bernstein} {,i:a} .+) {,} plt.plot
+  x ({a coeff bernstein} :{i:a} .+) :{} plt.plot
 }:fns;
 
 .# plot attributes
diff --git a/examples/plot/betting.aya b/examples/plot/betting.aya
index e4c62906..abd90e7f 100644
--- a/examples/plot/betting.aya
+++ b/examples/plot/betting.aya
@@ -53,7 +53,7 @@ plot.plot!:plt;
 games R :x;
 
 {plt r,
-    x (games r runsim) {, "$r":label} plt.plot
+    x (games r runsim) :{ "$r":label} plt.plot
 }:runit;
 
 [0.3 0.35 0.4 0.45 0.5 0.55] # {r,
diff --git a/examples/plot/box_plot.aya b/examples/plot/box_plot.aya
index 386c3e98..ea30ea75 100644
--- a/examples/plot/box_plot.aya
+++ b/examples/plot/box_plot.aya
@@ -1,17 +1,17 @@
 .{ An example of the minimum required parameters for drawing a box-plot .}
-{,
+:{
 	[
-		{, 10.R :values}
-		{, 15.R :values}
-		{, 20.R :values}
-		{, 15.R :values}
-		{, 10.R :values}
+		:{ 10.R :values}
+		:{ 15.R :values}
+		:{ 20.R :values}
+		:{ 15.R :values}
+		:{ 10.R :values}
 	] :data
 } :(plot.box_plot)
 
 
 .{ An example showing all parameters for box-plots .}
-{,
+:{
 	"An Example Box-Plot" :title
 	"#ddd" :bgcolor
 	["#222" "#444"] :color_cycle
@@ -19,13 +19,13 @@
 	0 :show_median
 	1 :show_average
 	1 :show_far_outliers
-	{,
+	:{
 		1 :gridlines
 		"#fff" :gridline_color
 		1 :visible
 		"x-axis" :label
 	} :x
-	{,
+	:{
 		1 :gridlines
 		"#fff" :gridline_color
 		1 :zeroline
@@ -36,11 +36,11 @@
 	500 :width
 	500 :height
 	[
-		{, [0 0.9 1 1.1 2] 0.1 + :values  "group1" :group  "1" :entry}
-		{, [0 0.9 1 1.1 2] 0.2 + :values  "group1" :group  "2" :entry}
-		{, [0 0.9 1 1.1 2] 0.3 + :values  "group1" :group  "3" :entry}
-		{, [0 0.9 1 1.1 2] 0.4 + :values  "group2" :group  "1" :entry}
-		{, [0 0.9 1 1.1 2] 0.5 + :values  "group2" :group  "2" :entry}
-		{, [0 0.9 1 1.1 2] 0.6 + :values  "group2" :group  "3" :entry}
+		:{ [0 0.9 1 1.1 2] 0.1 + :values  "group1" :group  "1" :entry}
+		:{ [0 0.9 1 1.1 2] 0.2 + :values  "group1" :group  "2" :entry}
+		:{ [0 0.9 1 1.1 2] 0.3 + :values  "group1" :group  "3" :entry}
+		:{ [0 0.9 1 1.1 2] 0.4 + :values  "group2" :group  "1" :entry}
+		:{ [0 0.9 1 1.1 2] 0.5 + :values  "group2" :group  "2" :entry}
+		:{ [0 0.9 1 1.1 2] 0.6 + :values  "group2" :group  "3" :entry}
 	] :data
 } :(plot.box_plot)
diff --git a/examples/plot/canvas_multiplot.aya b/examples/plot/canvas_multiplot.aya
index 08ae3d1e..f4209f4d 100644
--- a/examples/plot/canvas_multiplot.aya
+++ b/examples/plot/canvas_multiplot.aya
@@ -1,28 +1,28 @@
 import ::canvas
 
 20 :gap;
-{,
+:{
 	800 gap + :width
 	800 gap + :height
 	"Canvas Multiplot" :name
 } canvas! :c;
 
 .{ Add a box-plot in the top-left corner .}
-{,
+:{
 	0 :show
-	{,
+	:{
 		c.id :id
 		0 :x
 		0 :y
 	} :canvas
 	400 :width :height
-	[0 1 2 1 0] # {x, {, x 5* 10+ .R :values}} :data
+	[0 1 2 1 0] # {x, :{ x 5* 10+ .R :values}} :data
 } :(plot.box_plot)
 
 .{ Add a pie-chart in the bottom-left corner .}
-{,
+:{
 	0 :show
-	{,
+	:{
 		c.id :id
 		0 :x
 		400 gap + :y
@@ -32,9 +32,9 @@ import ::canvas
 } :(plot.pie_chart)
 
 .{ Add a multiplot in the right half .}
-{,
+:{
 	0 :show
-	{,
+	:{
 		c.id :id
 		400 gap + :x
 		0 :y
@@ -42,22 +42,22 @@ import ::canvas
 	400 :width
 	800 gap + :height
 	[
-		{,
+		:{
 			[
-				{, 10.R :x #{3*} :y "3*" :label}
+				:{ 10.R :x #{3*} :y "3*" :label}
 			] :data
 		}
-		{,
+		:{
 			[
-				{, 10.R :x #{3*} :y "3*" :label}
-				{, 10.R :x #{4*} :y "4*" :label}
+				:{ 10.R :x #{3*} :y "3*" :label}
+				:{ 10.R :x #{4*} :y "4*" :label}
 			] :data
 		}
-		{,
+		:{
 			[
-				{, 10.R :x #{3*} :y "3*" :label}
-				{, 10.R :x #{4*} :y "4*" :label}
-				{, 10.R :x #{5*} :y "5*" :label}
+				:{ 10.R :x #{3*} :y "3*" :label}
+				:{ 10.R :x #{4*} :y "4*" :label}
+				:{ 10.R :x #{5*} :y "5*" :label}
 			] :data
 		}
 	] :subplots
diff --git a/examples/plot/iris.aya b/examples/plot/iris.aya
index 5115a41d..70ce92e1 100644
--- a/examples/plot/iris.aya
+++ b/examples/plot/iris.aya
@@ -1,7 +1,7 @@
 import ::dataframe
 import ::plot
 
-{, "$(:(sys.ad))/examples/data/iris.csv":filename} dataframe.read_csv :df;
+:{ "$(:(sys.ad))/examples/data/iris.csv":filename} dataframe.read_csv :df;
 
 .# get unique species names
 df.["Species"] :~ :species;
@@ -13,7 +13,7 @@ plot.plot! :plt;
 
 species :# {s_name : sp_df,
     df.[df.["Species"] s_name .=] :sp_df;
-    sp_df.["Sepal.Length"] sp_df.["Sepal.Width"] {, s_name:label } plt.scatter
+    sp_df.["Sepal.Length"] sp_df.["Sepal.Width"] :{ s_name:label } plt.scatter
 };
 
 plt.view
diff --git a/examples/plot/lakehuron.aya b/examples/plot/lakehuron.aya
index 7f1299b2..5b5ab63e 100644
--- a/examples/plot/lakehuron.aya
+++ b/examples/plot/lakehuron.aya
@@ -6,7 +6,7 @@ import ::plot
 import ::stats
 
 "Downloading file..." :P
-{,
+:{
     "https://raw.githubusercontent.com/vincentarelbundock/Rdatasets/master/csv/datasets/LakeHuron.csv":filename
     1:csvindex
 }
@@ -20,8 +20,8 @@ df.["value"] :y;
 .# stats.regression returns a function
 x y stats.regression :r;
 
-x y   {, "Water Level":label} plt.plot
-x {r} {, "Trend":label} plt.plot
+x y   :{ "Water Level":label} plt.plot
+x {r} :{ "Trend":label} plt.plot
 
 "Water Level of Lake Huron" plt.:title;
 [575 583] plt.y.:lim;
diff --git a/examples/plot/multi.aya b/examples/plot/multi.aya
index 911e7953..6713febe 100644
--- a/examples/plot/multi.aya
+++ b/examples/plot/multi.aya
@@ -9,13 +9,13 @@ plot.multiplot! :mp;
 
 .# Upper plot
 plot.plot!:a;
-x {sin} {, "sin":label } a.plot
-x {0.3*} {, "0.3x":label } a.plot
+x {sin} :{ "sin":label } a.plot
+x {0.3*} :{ "0.3x":label } a.plot
 a mp.add
 
 .# Lower plot
 plot.plot!:b;
-x {x, x Ms x 0.3* +}  {, "sin(x)+0.3x":label  } b.plot
+x {x, x Ms x 0.3* +}  :{ "sin(x)+0.3x":label  } b.plot
 b mp.add
 
 .# Plot title
diff --git a/examples/plot/normal.aya b/examples/plot/normal.aya
index 24ab3ea4..63a5a3b6 100644
--- a/examples/plot/normal.aya
+++ b/examples/plot/normal.aya
@@ -6,7 +6,7 @@ import ::stats
 
 plot.plot! :plt;
 
-[l.min l.max] .R h {, "Frequency":label} plt.scatter
+[l.min l.max] .R h :{ "Frequency":label} plt.scatter
 
 "Normal Distribution" plt.:title;
 "Frequency" plt.:ylabel;
diff --git a/examples/plot/numdx.aya b/examples/plot/numdx.aya
index a81fdbcb..2b917c8b 100644
--- a/examples/plot/numdx.aya
+++ b/examples/plot/numdx.aya
@@ -17,7 +17,7 @@ import ::plot
 
 .# Generate a function for a tangent line at a point
 {a f : dx^,
-  {x, f_a fdx_a x a - * +} {, 
+  {x, f_a fdx_a x a - * +} :{ 
     a f :f_a;
     a f.`dx :fdx_a;
     a :a;
@@ -31,9 +31,9 @@ t fn.` tangent_line :f_;
 
 plot.plot! :p;
 
-x :& #fn       {, "f":label  } p.plot
-x :& #{fn.`dx} {, "f'":label } p.plot
-x :& #f_       {, "tangent@$t":label  } p.plot
+x :& #fn       :{ "f":label  } p.plot
+x :& #{fn.`dx} :{ "f'":label } p.plot
+x :& #f_       :{ "tangent@$t":label  } p.plot
 
 p.view
 
diff --git a/examples/plot/pie_chart.aya b/examples/plot/pie_chart.aya
index 5a827d6a..f244eec9 100644
--- a/examples/plot/pie_chart.aya
+++ b/examples/plot/pie_chart.aya
@@ -1,9 +1,9 @@
 .{ An example of the minimum required parameters for drawing a box-plot .}
-{,
+:{
 	[1 3 6] :data
 } :(plot.pie_chart)
 
-{,
+:{
 	"An Example Pie-Chart" :title
 	"#ddd" :bgcolor
 	["#222" "#444" "#666"] :color_cycle
@@ -13,8 +13,8 @@
 	300 :width
 	300 :height
 	[
-		{, 1:value  "a":label }
-		{, 3:value  "b":label }
-		{, 6:value  "c":label }
+		:{ 1:value  "a":label }
+		:{ 3:value  "b":label }
+		:{ 6:value  "c":label }
 	]:data
 } :(plot.pie_chart)
diff --git a/examples/plot/rainbow.aya b/examples/plot/rainbow.aya
index ea7bf882..b2b4d06d 100644
--- a/examples/plot/rainbow.aya
+++ b/examples/plot/rainbow.aya
@@ -14,7 +14,7 @@ plot.plot!:p;
 [0.9 :1p .9 - 600] .R :x;
 
 7R :# {i,
-    x {:i^, Ms i 0.011* +} {,} p.plot
+    x {:i^, Ms i 0.011* +} :{} p.plot
 };
 
 p.view
diff --git a/examples/plot/randomwalk.aya b/examples/plot/randomwalk.aya
index 122b7205..31517e7b 100644
--- a/examples/plot/randomwalk.aya
+++ b/examples/plot/randomwalk.aya
@@ -7,7 +7,7 @@ import ::plot
 {v, v.x 3QV+ v.:x; v.y 3QV+ v.:y;}:step;
 
 .# Start at (0,0)
-{,0:x 0:y}:v;
+:{0:x 0:y}:v;
 
 .# Record each step in a list, step 20000 times
 [] {v step [v.x v.y]\.V} 20000 %
diff --git a/examples/plot/scatter.aya b/examples/plot/scatter.aya
index 4ea61bb5..c4b41aca 100644
--- a/examples/plot/scatter.aya
+++ b/examples/plot/scatter.aya
@@ -7,7 +7,7 @@ plot.plot! :plt;
 [100,;.Q]:x;
 [100,;.Q]:y;
 
-x y {,} plt.scatter
+x y :{} plt.scatter
 
 "A Scatter Plot" plt.:title;
 0 plt.:legend;
diff --git a/examples/plot/simple_functions.aya b/examples/plot/simple_functions.aya
index 6c5beaa6..ceb0e970 100644
--- a/examples/plot/simple_functions.aya
+++ b/examples/plot/simple_functions.aya
@@ -7,10 +7,10 @@ plot.plot!:p;
 [0 2pi*] .R :x;
 
 .# Add each function
-x {sin} {, "sin":label } p.plot
-x {cos} {, "cos":label } p.plot
-x {tan} {, "tan":label [-3 3]:yclip} p.plot
-x {ln}  {, "ln":label  } p.plot
+x {sin} :{ "sin":label } p.plot
+x {cos} :{ "cos":label } p.plot
+x {tan} :{ "tan":label [-3 3]:yclip} p.plot
+x {ln}  :{ "ln":label  } p.plot
 
 .# Plot title
 "Example Expression Plot" p.:title;
diff --git a/examples/plot/sinsrs.aya b/examples/plot/sinsrs.aya
index 5e9a7fa6..ff37b90a 100644
--- a/examples/plot/sinsrs.aya
+++ b/examples/plot/sinsrs.aya
@@ -7,7 +7,7 @@ plot.plot!:plt;
 
 
 5R # {n,
-  x {x, [nR [nR, x*Ms], *] W} {, nP:label } plt.plot
+  x {x, [nR [nR, x*Ms], *] W} :{ nP:label } plt.plot
 };
 
 "Sine Series" plt.:title;
diff --git a/examples/plot/weierstrass.aya b/examples/plot/weierstrass.aya
index 20815d7d..72a630d4 100644
--- a/examples/plot/weierstrass.aya
+++ b/examples/plot/weierstrass.aya
@@ -12,7 +12,7 @@ import ::plot
 plot.plot! :plt;
 [-0.7 0.7 5000] .R :x;
 
-x {w} {,} plt.plot
+x {w} :{} plt.plot
 
 .# plot attributes
 "Weierstrass Function" plt.:title;
diff --git a/examples/quicksort.aya b/examples/quicksort.aya
index af3cf9df..a06e8f10 100644
--- a/examples/quicksort.aya
+++ b/examples/quicksort.aya
@@ -42,7 +42,7 @@ lst qs :P
 {.E1> {$\; :&V$@\< @\ :&#! @:&@.i \@.i qss @@qss JJ} ?}:qss;
 
 .# Stack only version with no global vars
-.# {.E1> {$\; :&V$@\< @\ :&#! @:&@.i \@.i _ @@_ JJ} ?} {1, :_} :+
+.# {.E1> {$\; :&V$@\< @\ :&#! @:&@.i \@.i _ @@_ JJ} ?} :{1, :_} :+
 
 .# Quicksort benchmark and example output
 .# aya> 10 R :# {; [100000,;.Q] {qs;}.time} :& .E \W\/
diff --git a/examples/rdatasets.aya b/examples/rdatasets.aya
index c991b1bd..210354b6 100644
--- a/examples/rdatasets.aya
+++ b/examples/rdatasets.aya
@@ -5,7 +5,7 @@
 
 import ::csv
 
-{,
+:{
 
     "https://raw.githubusercontent.com/vincentarelbundock/Rdatasets/master/csv":url;
 
diff --git a/examples/setindex.aya b/examples/setindex.aya
index c7cd41e2..03739e15 100644
--- a/examples/setindex.aya
+++ b/examples/setindex.aya
@@ -11,15 +11,15 @@
 9 newlist.[{:T::str=}];   x:P  .# [ 1 2 3 'a 'b 'c ]
 
 "Dicts":P
-{, 1:a 2:b 3:c} :dict;
+:{ 1:a 2:b 3:c} :dict;
 {dict$X;x}:newdict;
 
-9 newdict.:[::a];          x:P  .# {, 9:a; 2:b; 3:c; }
-9 newdict.:[::x];          x:P  .# {, 1:a; 2:b; 3:c; 9:x; }
+9 newdict.:[::a];          x:P  .# :{ 9:a; 2:b; 3:c; }
+9 newdict.:[::x];          x:P  .# :{ 1:a; 2:b; 3:c; 9:x; }
 
 .# setindex overload
 newdict :d;
-d {, {item index self,
+d :{ {item index self,
 "d.setindex:
   Item: $item
   Index: $index
diff --git a/examples/singleton.aya b/examples/singleton.aya
index d5fa88bf..fc093552 100644
--- a/examples/singleton.aya
+++ b/examples/singleton.aya
@@ -14,7 +14,7 @@ def singleton::add {self,
 
 impl_static singleton::get_instance {meta,
     meta._instance nil = {: self,
-        {,} meta MO: self .__init__
+        :{} meta MO: self .__init__
         self meta.:_instance;
     } ?
 
diff --git a/examples/syntax.aya b/examples/syntax.aya
index 75b5f60c..feca57da 100644
--- a/examples/syntax.aya
+++ b/examples/syntax.aya
@@ -86,12 +86,12 @@ _ a._ a:_
 .# Another comment!
 2500 rainprob 100.0 * :result;
 
-{,
+:{
 
     ::point:type;
 
     {x::num y::num,
-        {, x:x y:y} plot MO
+        :{ x:x y:y} plot MO
     }:new!;
 
     {other self, 
diff --git a/examples/turtle/flower.aya b/examples/turtle/flower.aya
index c4f9a18d..eaa3abc3 100644
--- a/examples/turtle/flower.aya
+++ b/examples/turtle/flower.aya
@@ -3,7 +3,7 @@
 import ::turtle
 import ::math
 
-{, } turtle!:t;
+:{ } turtle!:t;
 {
     {
         20 t.fd
diff --git a/examples/turtle/random.aya b/examples/turtle/random.aya
index 488cdadb..e15d9b77 100644
--- a/examples/turtle/random.aya
+++ b/examples/turtle/random.aya
@@ -8,11 +8,11 @@ import ::canvas
 import ::color
 
 .# The canvas to pass to the turtle
-{, 500:width; 500:height; } canvas! :cvs;
+:{ 500:width; 500:height; } canvas! :cvs;
 
 def ::newimage { : cvs^ ,
 
-    {, cvs :canvas; "#444" color.fromstr :bg_color; } turtle! :t;
+    :{ cvs :canvas; "#444" color.fromstr :bg_color; } turtle! :t;
     .# random bright color
     360Q 1.0 1.0 color.newhsv :c;
     .# Random number between 60 and 190
diff --git a/examples/turtle/snowflake.aya b/examples/turtle/snowflake.aya
index c5105302..e3435f2b 100644
--- a/examples/turtle/snowflake.aya
+++ b/examples/turtle/snowflake.aya
@@ -3,7 +3,7 @@
 import ::turtle
 import ::math
 
-{, } turtle!:t;
+:{ } turtle!:t;
 
 {
     {
diff --git a/examples/turtle/square.aya b/examples/turtle/square.aya
index 1f3e048b..24238361 100644
--- a/examples/turtle/square.aya
+++ b/examples/turtle/square.aya
@@ -5,7 +5,7 @@
 import ::turtle
 import ::color
 
-{,
+:{
     400:width;
     400:height;
     color.colors.darkblue :bg_color;
diff --git a/manual/blocks_and_functions.md b/manual/blocks_and_functions.md
index b656b201..1d6ed7db 100644
--- a/manual/blocks_and_functions.md
+++ b/manual/blocks_and_functions.md
@@ -43,7 +43,7 @@ If a colon is the first token in a block header, all variable names are consider
 Finally, if nothing is included in the block header, the block will be parsed as a dictionary.
 
 ```
-{, }
+:{ }
 ```
 
 ## Arguments
@@ -83,7 +83,7 @@ Arguments may have type assertions. Write a variable name followed by a symbol c
 If a user defined type defines a `type` variable as a symbol. The symbol will be used for type assertions.
 
 ```
-{,
+:{
   ::vec :type;
 
   ... define vec variables and functions ...
@@ -168,18 +168,18 @@ Aya provides a way to use keyword arguments using dictionaries and local declara
 The function `fn` contains 1 argument `kwargs` (the name can be anything) and three local declarations. The operator `.W` will export variables from the `kwargs` dict only if they are defined in the local scope. This means that any variables defined in `kwargs` will overwrite the initialized local variables. Every variable not given by `kwargs` dict will remain in its default state.
 
 ```
-aya> {, "sales.csv":filename 1:header} fn
+aya> :{ "sales.csv":filename 1:header} fn
 filename="sales.csv", header=1, dtype=::num
 
 aya> .# The variable `useless` does not exist in the local scope of `fn`
 aya> .#    and will therefore be ignored
-aya> {, "colors.csv":filename "blah":useless} fn
+aya> :{ "colors.csv":filename "blah":useless} fn
 filename="colors.csv", header=0, dtype=::num
 
-aya> {, "names.csv":filename ::str:dtype} fn
+aya> :{ "names.csv":filename ::str:dtype} fn
 filename="names.csv", header=0, dtype=::str
 
-aya> {, } fn
+aya> :{ } fn
 filename="", header=0, dtype=::num
 ```
 
diff --git a/manual/dictionaries.md b/manual/dictionaries.md
index 9b02ea69..fd9ad4d4 100644
--- a/manual/dictionaries.md
+++ b/manual/dictionaries.md
@@ -3,7 +3,7 @@
 A dictionary is a set of key-value pairs. The keys must always be valid variable names. A dictionary literal is created using a block with an empty header. The block is evaluated and all variables are in assigned in the scope of the dictionary.
 
 ```
-{,
+:{
   
 }
 ```
@@ -12,7 +12,7 @@ Below is a simple dictionary example.
 
 ```
 .# Define a simple dictionary
-{,
+:{
   1:one;
   2:two;
   3:three;
@@ -22,8 +22,8 @@ Below is a simple dictionary example.
 Empty dictionaries are created if the block and the header are empty.
 
 ```
-aya> {,}
-{,
+aya> :{}
+:{
 }
 ```
 
@@ -45,18 +45,18 @@ aya> numbers .one
 Dictionary values can be assigned using the `.:` operator.
 
 ```
-aya> {, 1:a 2:b} :d
-{,
+aya> :{ 1:a 2:b} :d
+:{
   1:a;
   2:b;
 }
 aya> 4 d.:a
-{,
+:{
   4:a;
   2:b;
 }
 aya> 9 d.:c
-{,
+:{
   4:a;
   2:b;
   9:c;
@@ -74,17 +74,17 @@ where `key` is a string or a symbol.
 For example:
 
 ```
-aya> {, 0:x } :dict;
+aya> :{ 0:x } :dict;
 aya> 1 dict.:[::y]
 aya> dict
-{,
+:{
   0:x;
   1:y;
 }
 
 aya> 1 dict.:["y"]
 aya> dict
-{,
+:{
   0:x;
   1:y;
 }
@@ -95,7 +95,7 @@ Loop over k/v pairs in a dict using the `:#` operator
 ```
 aya> dict :# {k v, v 1 + dict.:[k]}
 aya> dict
-{,
+:{
   1:x;
   2:y;
 }
@@ -107,20 +107,20 @@ In Aya, metatables can be used to define custom types with separate functionalit
 Any dictionary can contain a read-only set of variables as a metatable. Metatables typically contain functions that act on the dictionaries values. For example, if we define the metatable
 
 ```
-{, {self, self.x self.y +}:sum;  {}:donothing; } :meta;
+:{ {self, self.x self.y +}:sum;  {}:donothing; } :meta;
 ```
 
 and the dictionary
 
 ```
-{, 1:x 2:y {}:none } :dict;
+:{ 1:x 2:y {}:none } :dict;
 ```
 
 we can set the metatable using the MO operator like so
 
 ```
 aya> meta meta.:__meta__
-{,
+:{
   1:x;
   2:y;
   {}:none;
@@ -133,7 +133,7 @@ We can see that the dict still has the values `x` and `y` but it also now has a
 aya> dict.sum
 3
 aya> dict.donothing
-{,
+:{
   1:x;
   2:y;
   {}:none;
diff --git a/manual/multithreading.md b/manual/multithreading.md
index 50d3c974..61e9e8a2 100644
--- a/manual/multithreading.md
+++ b/manual/multithreading.md
@@ -257,7 +257,7 @@ x is 10
 For mutable data, changes are reflected but **no guarentees are made about the data being in sync across threads**. In general, mutable objects should not be updated if they are being shared between threads.
 
 ```
-aya> {, 10 :a } :x;
+aya> :{ 10 :a } :x;
 
 aya> .# wait for 10s in the thread
 aya> { : x^ , "thread start" 10000:Z "x is $x" :P } t.add_task ;
@@ -269,12 +269,12 @@ aya> 99 x.:a;
 
 aya> `x.a` is `99` in the main thread
 aya> x
-{,
+:{
   99:a;
 }
 
 aya> .# When the other thread accesses `x`, `x.a` is `10`, sometimes `x.a` is `99`
-x is {, 99:a; }
+x is :{ 99:a; }
 ```
 
 ### Getting data from a thread
diff --git a/manual/standard_library.md b/manual/standard_library.md
index 0b79bbd1..d2668b0b 100644
--- a/manual/standard_library.md
+++ b/manual/standard_library.md
@@ -100,7 +100,7 @@ Provides functions for reading and writing CSV files
 
 ```
 aya> "examples/data/simple.csv" csv.read
-{,
+:{
   [
     [ 1 2 3 ]
     [ 4 5 6 ]
@@ -117,12 +117,12 @@ aya> "examples/data/simple.csv" csv.read
 The `dataframe` type is an interface for working with tables. CSV files can be directly imported and modified or the data can be generated by the program itself.
 
 ```
-aya> {, [[1 2 3][4 5 6]]:data ["x" "y" "z"]:colnames} dataframe!
+aya> :{ [[1 2 3][4 5 6]]:data ["x" "y" "z"]:colnames} dataframe!
     x y z
 0 | 1 2 3
 1 | 4 5 6 
 
-aya> {, [[1 2 3][4 5 6]]:data ["x" "y" "z"]:colnames} dataframe! :df
+aya> :{ [[1 2 3][4 5 6]]:data ["x" "y" "z"]:colnames} dataframe! :df
     x y z
 0 | 1 2 3
 1 | 4 5 6 
diff --git a/manual/syntax_overview.md b/manual/syntax_overview.md
index 0a62b721..0e80545d 100644
--- a/manual/syntax_overview.md
+++ b/manual/syntax_overview.md
@@ -479,21 +479,21 @@ aya> 10 list.:[0]
 
 ### Dictionary Literals
 
-Dictionary literals have the form `{, ... }`. All variables assigned between `{,` and `}` are assigned to the dictionary
+Dictionary literals have the form `:{ ... }`. All variables assigned between `:{` and `}` are assigned to the dictionary
 
 ```
-aya> {, 1:a 2:b }
-{,
+aya> :{ 1:a 2:b }
+:{
   2:b;
   1:a;
 }
 ```
 
-`{,}` creates an empty dict
+`:{}` creates an empty dict
 
 ```
-aya> {,}
-{,}
+aya> :{}
+:{}
 ```
 
 ### Getting Values
@@ -501,8 +501,8 @@ aya> {,}
 Use dot notation to get values from a dict:
 
 ```
-aya> {, 1:a 2:b } :d
-{,
+aya> :{ 1:a 2:b } :d
+:{
   2:b;
   1:a;
 } 
@@ -533,8 +533,8 @@ aya> d "a" I
 Dot notation can be used with [quoted variables](#variables)
 
 ```
-aya> {, 1:"Hello, world!" } :d
-{,
+aya> :{ 1:"Hello, world!" } :d
+:{
   1:"Hello, world!";
 } 
 aya> d."Hello, world!"
@@ -547,10 +547,10 @@ aya> d."Hello, world!"
 Use `.:` notation to set values of a dict
 
 ```
-aya> {,} :d
-{,} 
+aya> :{} :d
+:{} 
 aya> 10 d.:a
-{,
+:{
   10:a;
 } 
 ```
@@ -559,12 +559,12 @@ Or using strings or symbols with index notation (`.:[]`)
 
 ```
 aya> 11 d.:["b"]
-{,
+:{
   11:b;
   10:a;
 } 
 aya> 12 d.:[::c]
-{,
+:{
   11:b;
   10:a;
   12:c;
@@ -574,10 +574,10 @@ aya> 12 d.:[::c]
 This notation can be used with [quoted variables](#variables)
 
 ```
-aya> {,}:d
-{,} 
+aya> :{}:d
+:{} 
 aya> 10 d.:"Hello, world!"
-{,
+:{
   10:"Hello, world!";
 } 
 ```
@@ -635,8 +635,8 @@ See [Variables and Scope](./variables_and_scope.md) and [Blocks and Functions](.
 If the header is empty, the block is parsed as a dict (see *Dictionary*)
 
 ```
-aya> {, 1:a }
-{,
+aya> :{ 1:a }
+:{
   1:a;
 } 
 ```
@@ -910,8 +910,8 @@ aya> p.format
 Any single-character key stored in `__cdict__` can be accessed using `¢` + that character
 
 ```
-aya> {, "Hello!":"!" 10:a }:__cdict__
-{,
+aya> :{ "Hello!":"!" 10:a }:__cdict__
+:{
   "Hello!":"!";
 } 
 aya> ¢!
diff --git a/manual/tour.md b/manual/tour.md
index 4518bd62..c38399ca 100644
--- a/manual/tour.md
+++ b/manual/tour.md
@@ -96,7 +96,7 @@ aya> [1 2 3] :T
 ::list
 aya> [1 2 3] :T :T
 ::sym
-aya> [ 1 [1 2 3] "hello" 'c {, 1:x } {2+} ::red ] #:T
+aya> [ 1 [1 2 3] "hello" 'c :{ 1:x } {2+} ::red ] #:T
 [ ::num ::list ::str ::char ::dict ::block ::sym ]
 ```
 
@@ -173,21 +173,21 @@ TYPE ERROR: {ARGS}
     Received: "dogs"
 ```
 
-Aya also supports dictionaries. `{,}` creates an empty dictionary. `.` is used for dictionary access and `.:` is used for assignment.
+Aya also supports dictionaries. `:{}` creates an empty dictionary. `.` is used for dictionary access and `.:` is used for assignment.
 
 ```
-aya> {,} :d
-{,
+aya> :{} :d
+:{
 }
 aya> 3 d.:x
-{,
+:{
   3:x;
 }
 aya> d.x
 3
 aya> .# Keys can also be assigned in the literal itself
-aya> {, 3:x; }
-{,
+aya> :{ 3:x; }
+:{
   3:x;
 }
 ```
diff --git a/manual/user_types.md b/manual/user_types.md
index 52d6c688..d6e9150e 100644
--- a/manual/user_types.md
+++ b/manual/user_types.md
@@ -305,14 +305,14 @@ Classes, structs, and object instances are simply dictionaries with special __me
 Below is an example of a 2d vector "class" definition written *from scratch* without using any convience functions. Member functions and overloads work the same as they do for normal classes. The only major difference is object creation (`__new__` vs `__init__`) and the special variables `__pushself__` and `__type__` at the top of the metatable.
 
 ```
-{,
+:{
 
   1:__pushself__;
   ::vec:__type__;
 
   .# Constructor
   {x y cls,
-    {,
+    :{
       x:x;
       y:y;
       cls:__meta__;
@@ -357,7 +357,7 @@ The symbol assigned to `__type__` is used for type checking and overloading the
 
 ```
 {x y cls,
-    {,
+    :{
         x:x;
         y:y;
         cls:__meta__;
diff --git a/src/aya/TypeIDs.java b/src/aya/TypeIDs.java
index eef8c79f..60992183 100644
--- a/src/aya/TypeIDs.java
+++ b/src/aya/TypeIDs.java
@@ -33,4 +33,7 @@ public class TypeIDs {
 	public static final byte T_FN_QUOTE 	   = 126; // (.`) function quote
 	public static final byte T_COLON_POUND 	   = 127; // (:#) special operator
 	public static final byte T_NAMED_OP        = 90;  // :(...)
+	public static final byte T_DICT 		   = 91;  // :{...} dict
+	
+	public static final int T_NEXT_BLOCK_IS_DICT = 92; // :{}
 }
diff --git a/src/aya/ext/image/AyaImage.java b/src/aya/ext/image/AyaImage.java
index 435fbab3..da8c0fa0 100644
--- a/src/aya/ext/image/AyaImage.java
+++ b/src/aya/ext/image/AyaImage.java
@@ -20,11 +20,11 @@
 /**
  * Implements the data-type for Image instructions:
  * 
{@code
- * {,
+ * :{
  *     .# meta information about the image.
  *     .# :(image.read) provides this information
  *     .# :(image.write) infers these values unless specified
- *     {,
+ *     :{
  *          :gray
  *          :alpha
  *          :premultiplied
diff --git a/src/aya/ext/plot/instruction/PieChartInstruction.java b/src/aya/ext/plot/instruction/PieChartInstruction.java
index c2036bd8..d92a9648 100644
--- a/src/aya/ext/plot/instruction/PieChartInstruction.java
+++ b/src/aya/ext/plot/instruction/PieChartInstruction.java
@@ -34,7 +34,7 @@ public PieChartInstruction() {
                 + "  labels_on_chart::num (bool) : overlay the labels onto the chart. default=false\n"
                 + RenderConfig.getDocString("  ")
                 + "  data::list : list of num or dict\n"
-                + "      ::num : The value of the entry. Same as {, num:value}\n"
+                + "      ::num : The value of the entry. Same as :{ num:value}\n"
                 + "      ::dict :\n"
                 + "          label::str : label of the entry. defaults to index\n"
                 + "          value::str : value of the entry\n"
@@ -67,7 +67,7 @@ private static class Input {
         public final RenderConfig renderConfig;
         /**
          * Provided as a list, where each entry is either:
-         * 

- a dictionary, e.g. {, "str":label 123:value} + *

- a dictionary, e.g. :{ "str":label 123:value} *

- a number, in which case the index is used as the label */ public final java.util.List data; diff --git a/src/aya/instruction/DictLiteralInstruction.java b/src/aya/instruction/DictLiteralInstruction.java index d219e598..3d5bb384 100644 --- a/src/aya/instruction/DictLiteralInstruction.java +++ b/src/aya/instruction/DictLiteralInstruction.java @@ -73,7 +73,7 @@ public void execute(BlockEvaluator b) { @Override public ReprStream repr(ReprStream stream) { if (num_captures == 0) { - stream.print("{,"); + stream.print(":{"); } else { stream.print("{" + num_captures + ","); } diff --git a/src/aya/instruction/EmptyDictLiteralInstruction.java b/src/aya/instruction/EmptyDictLiteralInstruction.java index fad89c23..4b10f074 100644 --- a/src/aya/instruction/EmptyDictLiteralInstruction.java +++ b/src/aya/instruction/EmptyDictLiteralInstruction.java @@ -32,6 +32,6 @@ public Dict getDict() { @Override public String toString() { - return "{,}"; + return ":{}"; } } diff --git a/src/aya/instruction/op/Operator.java b/src/aya/instruction/op/Operator.java index 110358df..c861058b 100644 --- a/src/aya/instruction/op/Operator.java +++ b/src/aya/instruction/op/Operator.java @@ -115,7 +115,7 @@ public Dict getInfo() { // ::sym:type; info.set(SymbolConstants.TYPE, _doc.typeSymbol()); - // {,}:doc; + // :{}:doc; info.set(SymbolConstants.DOC, _doc.toDict()); return info; diff --git a/src/aya/obj/dict/Dict.java b/src/aya/obj/dict/Dict.java index 6d567c9b..9d1e3a9b 100644 --- a/src/aya/obj/dict/Dict.java +++ b/src/aya/obj/dict/Dict.java @@ -245,7 +245,7 @@ public ReprStream repr(ReprStream stream) { dictRepr(stream); stream.popVisited(this); } else { - stream.print("{, ...}"); + stream.print(":{ ...}"); } return stream; } @@ -347,7 +347,7 @@ private ReprStream dictRepr(ReprStream stream) { try { blk_repr.eval(); } catch (AyaRuntimeException ex) { - stream.print("{, }"); + stream.print(":{ }"); return stream; } Obj obj_res = blk_repr.pop(); @@ -367,9 +367,9 @@ private ReprStream dictRepr(ReprStream stream) { } else { // Normal repr if (_vars.size() == 0) { - stream.print("{,}"); + stream.print(":{}"); } else { - stream.println("{,"); + stream.println(":{"); stream.incIndent(); stream.currentLineMatchIndent(); for (Symbol sym : _vars.keySet()) { diff --git a/src/aya/parser/Parser.java b/src/aya/parser/Parser.java index b35d5fd0..bef6e17b 100644 --- a/src/aya/parser/Parser.java +++ b/src/aya/parser/Parser.java @@ -40,6 +40,7 @@ import aya.parser.tokens.BlockToken; import aya.parser.tokens.CDictToken; import aya.parser.tokens.CharToken; +import aya.parser.tokens.DictToken; import aya.parser.tokens.KeyVarToken; import aya.parser.tokens.LambdaToken; import aya.parser.tokens.ListToken; @@ -394,6 +395,11 @@ else if (in.peek() == '#') { tokens.add(new SpecialToken(Token.COLON_POUND, ":#", in.currentRef())); in.next(); // Skip the # } + + // Dict Literal + else if (in.peek() == '{') { + tokens.add(new SpecialToken(Token.NEXT_BLOCK_IS_DICT, ":", in.currentRef())); + } // Quoted variable else if (in.peek() == '"') { @@ -486,13 +492,21 @@ public static NumberToken parseNumber(ParserString in) throws EndOfInputError, S public static TokenQueue assemble(TokenQueue in) throws EndOfInputError, SyntaxError { TokenQueue out = new TokenQueue(); - + boolean next_block_is_dict = false; + while (in.hasNext()) { Token current = in.next(); - + + switch (current.getType()) { + case Token.NEXT_BLOCK_IS_DICT: + next_block_is_dict = true; + break; case Token.OPEN_CURLY: - closeDelim(Token.OPEN_CURLY, Token.CLOSE_CURLY, Token.BLOCK, in, out, current.getSourceStringRef()); + closeDelim(Token.OPEN_CURLY, Token.CLOSE_CURLY, + next_block_is_dict ? Token.DICT : Token.BLOCK, + in, out, current.getSourceStringRef()); + next_block_is_dict = false; break; case Token.OPEN_SQBRACKET: closeDelim(Token.OPEN_SQBRACKET, Token.CLOSE_SQBRACKET, Token.LIST, in, out, current.getSourceStringRef()); @@ -513,6 +527,10 @@ public static TokenQueue assemble(TokenQueue in) throws EndOfInputError, SyntaxE default: out.add(current); } + + if (next_block_is_dict && current.getType() != Token.NEXT_BLOCK_IS_DICT) { + throw new SyntaxError("Internal error parsing this token. Expected next token to be a dict", current.getSourceStringRef()); + } } return out; @@ -558,6 +576,9 @@ else if (currentType == close) { innerTokens = assemble(innerTokens); switch (type) { + case Token.DICT: + out.add(new DictToken(debugStr.toString(), innerTokens.getArrayList(), source)); + break; case Token.BLOCK: out.add(new BlockToken(debugStr.toString(), innerTokens.getArrayList(), source)); break; diff --git a/src/aya/parser/tokens/BlockToken.java b/src/aya/parser/tokens/BlockToken.java index 4957258e..b851bccf 100644 --- a/src/aya/parser/tokens/BlockToken.java +++ b/src/aya/parser/tokens/BlockToken.java @@ -7,8 +7,6 @@ import aya.exceptions.parser.ParserException; import aya.exceptions.parser.SyntaxError; import aya.instruction.BlockLiteralInstruction; -import aya.instruction.DictLiteralInstruction; -import aya.instruction.EmptyDictLiteralInstruction; import aya.instruction.Instruction; import aya.instruction.InstructionStack; import aya.instruction.variable.QuoteGetVariableInstruction; @@ -50,15 +48,18 @@ public Instruction getInstruction() throws ParserException { if (blockData.size() == 2) { //Empty header, dict literal if (!header.hasNext()) { - InstructionStack instructions = Parser.generate(blockData.get(1)); - if (instructions.size() == 0) { - return EmptyDictLiteralInstruction.INSTANCE; - } else { - return new DictLiteralInstruction(this.getSourceStringRef(), BlockUtils.fromIS(instructions)); - } + throw new SyntaxError("Block cannot have an empty header", source); + //InstructionStack instructions = Parser.generate(blockData.get(1)); + //if (instructions.size() == 0) { + // return EmptyDictLiteralInstruction.INSTANCE; + //} else { + // return new DictLiteralInstruction(this.getSourceStringRef(), BlockUtils.fromIS(instructions)); + //} } // Single number in header, create a dict factory with a capture else if (header.size() == 1 && header.peek() instanceof NumberToken) { + throw new SyntaxError("Block cannot have a number in header", source); + /* NumberToken nt = (NumberToken)header.peek(); int n = 0; try { @@ -76,6 +77,7 @@ else if (header.size() == 1 && header.peek() instanceof NumberToken) { } else { return new DictLiteralInstruction(this.getSourceStringRef(), BlockUtils.fromIS(instructions), n); } + */ } //Non-empty header, args and local variables else { diff --git a/src/aya/parser/tokens/DictToken.java b/src/aya/parser/tokens/DictToken.java new file mode 100644 index 00000000..cbbb62e0 --- /dev/null +++ b/src/aya/parser/tokens/DictToken.java @@ -0,0 +1,71 @@ +package aya.parser.tokens; + +import java.util.ArrayList; + +import aya.exceptions.parser.ParserException; +import aya.exceptions.parser.SyntaxError; +import aya.instruction.DictLiteralInstruction; +import aya.instruction.EmptyDictLiteralInstruction; +import aya.instruction.Instruction; +import aya.instruction.InstructionStack; +import aya.obj.block.BlockUtils; +import aya.parser.Parser; +import aya.parser.SourceStringRef; +import aya.parser.token.TokenQueue; + +public class DictToken extends CollectionToken { + + public DictToken(String data, ArrayList col, SourceStringRef source) { + super(Token.DICT, data, col, source); + } + + @Override + public Instruction getInstruction() throws ParserException { + //Split Tokens where there are commas + ArrayList blockData = splitCommas(col); + + if (blockData.size() == 1) { + InstructionStack instructions = Parser.generate(blockData.get(0)); + if (instructions.size() == 0) { + return EmptyDictLiteralInstruction.INSTANCE; + } else { + return new DictLiteralInstruction(this.getSourceStringRef(), BlockUtils.fromIS(instructions)); + } + } else if (blockData.size() == 2) { + TokenQueue header = blockData.get(0); + + // Single number in header, create a dict factory with a capture + if (header.size() == 1 && header.peek() instanceof NumberToken) { + + NumberToken nt = (NumberToken)header.peek(); + int n = 0; + try { + n = nt.numValue().toInt(); + } catch (NumberFormatException e) { + throw new SyntaxError(nt + " is not a valid number in the blockEvaluator header", nt.getSourceStringRef()); + } + + if (n < 1) { + throw new SyntaxError("Cannot capture less than 1 elements from outer stack in a dict literal", nt.getSourceStringRef()); + } + InstructionStack instructions = Parser.generate(blockData.get(1)); + if (n == 0 && instructions.isEmpty()) { + return EmptyDictLiteralInstruction.INSTANCE; + } else { + return new DictLiteralInstruction(this.getSourceStringRef(), BlockUtils.fromIS(instructions), n); + } + } else { + throw new SyntaxError("dict headers not supported (yet)", source); + } + + } else { + throw new SyntaxError("Dict headers not supported (yet)", source); + } + } + + @Override + public String typeString() { + return "dict"; + } + +} diff --git a/src/aya/parser/tokens/Token.java b/src/aya/parser/tokens/Token.java index 77f9f971..6db4d954 100644 --- a/src/aya/parser/tokens/Token.java +++ b/src/aya/parser/tokens/Token.java @@ -46,6 +46,9 @@ public abstract class Token { public static final int COLON_POUND = TypeIDs.T_COLON_POUND; public static final int NAMED_OP = TypeIDs.T_NAMED_OP; + public static final int DICT = TypeIDs.T_DICT; + public static final int NEXT_BLOCK_IS_DICT = TypeIDs.T_NEXT_BLOCK_IS_DICT; + protected Token(int type, SourceStringRef source) { this.type = type; diff --git a/std/bitset.aya b/std/bitset.aya index 6274ab72..011f0fd2 100644 --- a/std/bitset.aya +++ b/std/bitset.aya @@ -8,14 +8,14 @@ export ::bitset def bitset::__new__ {s meta, s :T ::num = { - {, s:size 0sL:bits } meta :M + :{ s:size 0sL:bits } meta :M } { s meta.fromlist } .? } def bitset::fromlist {l::list : bitset^, - {, lE:size l:bits } bitset :M + :{ lE:size l:bits } bitset :M } diff --git a/std/canvas.aya b/std/canvas.aya index 75ebbff1..a62ac9b3 100644 --- a/std/canvas.aya +++ b/std/canvas.aya @@ -8,7 +8,7 @@ class canvas def canvas::__init__ {params::dict self : color^, .# Default values - {, + :{ 400 :width 400 :height "Canvas" :name @@ -40,7 +40,7 @@ def canvas::delay {self, } def canvas::line {xa ya xb yb self, - .# ::line {, xa:xa ya:ya xb:xb yb:yb } self.id :(graphics.MG) ; + .# ::line :{ xa:xa ya:ya xb:xb yb:yb } self.id :(graphics.MG) ; xa ya xb yb self.id :(graphics.line) } @@ -49,7 +49,7 @@ def canvas::path {xs::list ys::list fill::num self, } def canvas::point {x y self, - .#::line {, x:xa:xb y:ya:yb} self.id :(graphics.MG) ; + .#::line :{ x:xa:xb y:ya:yb} self.id :(graphics.MG) ; x y x y self.id :(graphics.line) } @@ -66,12 +66,12 @@ def canvas::points {points r self, } def canvas::set_color {color self, - .# ::set_color {, color.r:r color.g:g color.b:b } self.id :(graphics.MG) ; + .# ::set_color :{ color.r:r color.g:g color.b:b } self.id :(graphics.MG) ; color.r color.g color.b self.id :(graphics.set_color) } def canvas::set_alpha {a self, - .# ::set_alpha {, a:a } self.id :(graphics.MG) ; + .# ::set_alpha :{ a:a } self.id :(graphics.MG) ; a self.id :(graphics.set_alpha) } @@ -79,12 +79,12 @@ def canvas::set_stroke_width {n::num self, n self.id :(graphics.set_stroke_width) } -def canvas::cap {,} +def canvas::cap :{} "butt" canvas.cap.:butt; "round" canvas.cap.:round; "square" canvas.cap.:square; -def canvas::join {,} +def canvas::join :{} "bevel" canvas.join.:bevel; "miter" canvas.join.:miter; "round" canvas.join.:round; @@ -101,7 +101,7 @@ def canvas::set_grad {start::list ca::color end::list cb::color cycle::num self, } def canvas::set_bg {color self, - .# ::set_bg {, color.r:r color.g:g color.b:b } self.id :(graphics.MG) ; + .# ::set_bg :{ color.r:r color.g:g color.b:b } self.id :(graphics.MG) ; color.r color.g color.b self.id :(graphics.set_bgcolor) } @@ -115,7 +115,7 @@ def canvas::save {filename self, } def canvas::close {self, - .# ::close {,} self.id :(graphics.MG) ; + .# ::close :{} self.id :(graphics.MG) ; self.id :(graphics.close) } @@ -128,12 +128,12 @@ def canvas::isopen {self, } def canvas::rect {x y w h self, - .# ::rect {, x:x y:y w:w h:h } self.id :(graphics.MG) ; + .# ::rect :{ x:x y:y w:w h:h } self.id :(graphics.MG) ; x y w h 0 self.id :(graphics.rect) } def canvas::fillrect {x y w h self, - .# ::rect {, x:x y:y w:w h:h 1:fill} self.id :(graphics.MG) ; + .# ::rect :{ x:x y:y w:w h:h 1:fill} self.id :(graphics.MG) ; x y w h 1 self.id :(graphics.rect) } diff --git a/std/color.aya b/std/color.aya index 93677639..7b40994c 100644 --- a/std/color.aya +++ b/std/color.aya @@ -186,7 +186,7 @@ def color::rgbtohsv {r g b color : h s v delta maxv minv, .} module colors -{, +:{ :(color.name_list) :# {color_name : color_dict, color_name :(color.fromstr) :color_dict; color_dict.r color_dict.g color_dict.b color! color_name := diff --git a/std/csv.aya b/std/csv.aya index 43201cd7..45cc537a 100644 --- a/std/csv.aya +++ b/std/csv.aya @@ -17,7 +17,7 @@ def csv::read { arg : csv^ , { (arg :T ::str =) { .# convert to dict - {, arg :filename } + :{ arg :filename } } (arg :T ::dict =) { arg } { @@ -67,7 +67,7 @@ def csv::_read_kw {kwargs::dict : csv^ data :#{V\;} :rownames; } ? - {, + :{ data:data colnames:colnames rownames:rownames diff --git a/std/dataframe.aya b/std/dataframe.aya index 81d59695..ca59be86 100644 --- a/std/dataframe.aya +++ b/std/dataframe.aya @@ -62,7 +62,7 @@ def dataframe::_gen_colnames {n::num cls, .########### def dataframe::from_csv {csv_dict cls, - {, + :{ csv_dict.data :data; csv_dict.rownames :index; csv_dict.colnames :colnames; @@ -108,7 +108,7 @@ def dataframe::_numgetindex {index::num self : dataframe^ idx, self._index index N :idx; idx 0 :> { - {, + :{ [self._data.[idx]] :data; [self._index.[idx]] :index; self._colnames :colnames; @@ -129,7 +129,7 @@ def dataframe::__getindex__ { index self : dataframe^, index self._get_col } (index :T ::list =) { index E self._data E = { - {, + :{ self._data index .i :data; self._index index .i :index; self._colnames :colnames; @@ -161,7 +161,7 @@ def dataframe::row {(1 hold)({self index : data, self._data.[index~]:data; [ index~ :T ::num = { [data]:data } ? ]; - {, self._colnames:colnames data:data } dataframe! + :{ self._colnames:colnames data:data } dataframe! })} diff --git a/std/date.aya b/std/date.aya index 4149410e..a261655f 100644 --- a/std/date.aya +++ b/std/date.aya @@ -9,27 +9,27 @@ export [::date ::dates ::dateunit] -{, +:{ ::date :__type__; 1 :__pushself__; - {{,M$:ms} date :M}:now; + {:{M$:ms} date :M}:now; .# {in meta, [ - .# in:T ::num = {{,in:ms} meta :M} ? - .# in:T ::str = {{,in "yyyy-MM-dd" :(date.parse):ms} meta :M} ? + .# in:T ::num = {:{in:ms} meta :M} ? + .# in:T ::str = {:{in "yyyy-MM-dd" :(date.parse):ms} meta :M} ? .# {"Expected S|D, recieved: $in".D} .# ].S }:__new__; {in meta, { (in :T ::num =) { - {, + :{ in:ms } meta :M } (in :T ::str =) { - {, + :{ in "yyyy-MM-dd" :(date.parse) :ms; } meta :M } { @@ -75,7 +75,7 @@ export [::date ::dates ::dateunit] }:date; .#? dateunit\n static namespace defining units related to dates -{, +:{ [ ["year" 31536000000] ["month" 2628000000] @@ -89,10 +89,10 @@ export [::date ::dates ::dateunit] units # {u : name conv, u0I:name; u1I:conv; - {, + :{ 1 :__pushself__; - {n::num meta, {,n:n} meta :M}:__new__; - {.n x +} {, " dates.$name":x} .+ :__repr__; + {n::num meta, :{n:n} meta :M}:__new__; + {.n x +} :{ " dates.$name":x} .+ :__repr__; {.n conv*}.use[::conv]:ms; {date.__radd__.`~}:__add__; {date.__rsub__.`~}:__sub__; @@ -101,7 +101,7 @@ export [::date ::dates ::dateunit] }:dateunit; .#? dates\n static namespace for date related variables -{, +:{ .# Units dateunit.units # {u : name, u0I:name; diff --git a/std/docs.aya b/std/docs.aya index fbb3f54b..5382eb19 100644 --- a/std/docs.aya +++ b/std/docs.aya @@ -60,7 +60,7 @@ .{? docs: dictionaries dicts are created using the following syntax - {, val1:key1 val2:key2 ... valN:keyN} + :{ val1:key1 val2:key2 ... valN:keyN} .} .{? docs: special characters diff --git a/std/docstr.aya b/std/docstr.aya index b25e5906..05cea9b3 100644 --- a/std/docstr.aya +++ b/std/docstr.aya @@ -1,5 +1,5 @@ {f: argtypes args d, - {,}:d; + :{}:d; f.`.M W args :# {k, k :C argtypes.[k] "" arg! k d :D @@ -39,10 +39,10 @@ def docstr::__init__ {name string::str self, id self.:_name; string self.:_full_str; - {,} self.:sections; + :{} self.:sections; { self._parse self.:sections; } {err, "Error parsing docstr:\n$err" .D} .K - {,} self.:_args; + :{} self.:_args; self.sections ::args H { self._parseargs self.:_args; } ? @@ -52,14 +52,14 @@ def docstr::_parse {self : m("@.+:\n") d keys vals, self._full_str m & #{.trim B; V;} "desc" \J :keys; self._full_str "@.+:\n" S :# {.trim.lines :# {.trim"\n"+}W.trim}:vals; - {,}:sections; + :{}:sections; vals keys {sections :D} .&; sections } .# Inner class -docstr {, class arg} .+; +docstr :{ class arg} .+; def (docstr.arg)::__init__ {name desc self, name.[0] ': = self.:is_stack_arg; @@ -167,12 +167,12 @@ def docstr::_get_name {self, def docstr::_get__doc__ {self, d._module nil = { .# Access from scope - {__doc__;} {;{,}:__doc__;} .K + {__doc__;} {;:{}:__doc__;} .K __doc__ } { .# Access from module - {d._module.__doc__;} {; {,} d._module.:__doc__;} .K + {d._module.__doc__;} {; :{} d._module.:__doc__;} .K d._module.__doc__ } .? diff --git a/std/enum.aya b/std/enum.aya index 27681fee..74242499 100644 --- a/std/enum.aya +++ b/std/enum.aya @@ -8,7 +8,7 @@ export ::enum {class::sym enums::list : dict meta, .# The metatable for each enum member - {, + :{ class :__type__; 1 :__pushself__; {self, "$(self.__type__:C).$(self.name:C)"}:__str__:__repr__; @@ -19,15 +19,15 @@ export ::enum }:meta; .# The enum dict - {, class:name }:dict; + :{ class:name }:dict; .# Add each element to the enum dict enums # {e, - {,e:name} meta :M e dict :D ; + :{e:name} meta :M e dict :D ; }; .# Create and add the metatable for the enum - dict {, + dict :{ 1 :__pushself__; ::enum :__type__; {.name:C}:__repr__:__str__; diff --git a/std/golf.aya b/std/golf.aya index 30721c33..8b05551a 100644 --- a/std/golf.aya +++ b/std/golf.aya @@ -13,7 +13,7 @@ exportall } ; .# Standard library shortcuts -{, +:{ 0 .M :num; 'x.M :char; [].M :list; @@ -84,7 +84,7 @@ matrix:m; .# cdict variables -{, +:{ "()" :"("; "<>" :"<"; "/\\":"^"; diff --git a/std/io.aya b/std/io.aya index cb9d3ae7..2af02413 100644 --- a/std/io.aya +++ b/std/io.aya @@ -24,7 +24,7 @@ class path } { 1 :absolute_path; } .? - {, + :{ dir meta._split :dirs; absolute_path :is_absolute_path; } meta :M @@ -174,7 +174,7 @@ def path::_iswindows {self, "~" :(sys.resolvehome) path! path.:home; -{, :(sys.wd) path._split :dirs} path :M path.:dfltworking; +:{ :(sys.wd) path._split :dirs} path :M path.:dfltworking; @@ -280,7 +280,7 @@ def file::_do {blk__::block self__, } .#? stdin::file\n standard input stream -{, +:{ 1:id; .# Overloads @@ -292,7 +292,7 @@ def file::_do {blk__::block self__, } file :M :stdin; .#? stdout::file\n standard output stream -{, +:{ 2:id; .# Overloads @@ -326,7 +326,7 @@ def dummyfile::close {self, dummyfile file.:dummyfile ; -{, +:{ {path, .# ::path or ::str path P :(fileutils.readallbytes) }:readallbytes; diff --git a/std/map.aya b/std/map.aya index e8d0d039..2a4ba408 100644 --- a/std/map.aya +++ b/std/map.aya @@ -60,13 +60,13 @@ def map::__getindex__ {key self : idx, .#? ::block ::map.__each__\n apply the block to each key value pair .{ Example: aya> [[1 "one"][2 "two"]] map.fromlist :m -{, +:{ [ 1 2 ]:keys; [ "one" "two" ]:values; } aya> m :# {k v, v.upper k m.put} aya> m -{, +:{ [ 1 2 ]:keys; [ "ONE" "TWO" ]:values; } diff --git a/std/math.aya b/std/math.aya index 138f3527..ecb77d6e 100644 --- a/std/math.aya +++ b/std/math.aya @@ -161,7 +161,7 @@ exportall aya> [4,double] [ 2 4 6 8 ] .} -.# {.E .R U {2, :c ; :p} {p ^ c * W} \ .+}:makepoly; +.# {.E .R U :{2, :c ; :p} {p ^ c * W} \ .+}:makepoly; { [1| .E .R U {^} \ {*W} ].* }:makepoly; diff --git a/std/matrix.aya b/std/matrix.aya index b5fb2956..cc21d9d5 100644 --- a/std/matrix.aya +++ b/std/matrix.aya @@ -23,7 +23,7 @@ def matrix::__init__ {input::list self, .# Use this instead of the constructor to avoid .# validating the list def matrix::_new {matrix, - {1, :rows} matrix :M + :{1, :rows} matrix :M } .{ Example: @@ -130,7 +130,7 @@ def matrix::__radd__ {self n::num, sym.op :op; def matrix sym ({ :& .rows op #~ \.M._new - } {, op.`:op } .+ + } :{ op.`:op } .+ ) } @@ -161,8 +161,8 @@ def matrix::__eq__ ({a b, .# swap args if b is not a matrix b :T ::matrix =! {\} ? __fn 3.$ :T I ~ -} {, - {, +} :{ + :{ matrix._eq_list.` :list; matrix._eq_num.` :num; matrix._eq_mat.` :matrix; diff --git a/std/missing.aya b/std/missing.aya index 951de8c0..0ebe07e4 100644 --- a/std/missing.aya +++ b/std/missing.aya @@ -1,4 +1,4 @@ -{,} {, +:{} :{ ::missing:__type__; {; "Cannot create instance of missing" .D}:__new__; {"missing"}:__str__:__repr__; diff --git a/std/plot.aya b/std/plot.aya index 283e988b..8322e4f9 100644 --- a/std/plot.aya +++ b/std/plot.aya @@ -24,8 +24,8 @@ def plot::_supress_windows 0 def plot::__init__ {self, [] self.:data; - {,} self.:y; - {,} self.:x; + :{} self.:y; + :{} self.:x; } @@ -94,8 +94,8 @@ def plot::view {self, def multiplot::__init__ {self, [] self.:subplots; - {,} self.:y; - {,} self.:x; + :{} self.:y; + :{} self.:x; } def multiplot::add {plot self, @@ -116,7 +116,7 @@ def multiplot::view {self : plot^, .# Create a line plot with default paramaters and x,y as a dataset def ::line {x::list y::list : p plot^, plot! :p; - x y {,} p.plot + x y :{} p.plot 0 p.:legend; p } @@ -126,7 +126,7 @@ def ::fns {fns::list a::num b::num : x p plot^, plot! :p; [a b 300] .R :x; fns {f, - x :& f.` O {, f.`P:label} p.plot + x :& f.` O :{ f.`P:label} p.plot } O; 1 p.:legend; p diff --git a/std/rdatasets.aya b/std/rdatasets.aya index 61a7ded8..b614de79 100644 --- a/std/rdatasets.aya +++ b/std/rdatasets.aya @@ -8,7 +8,7 @@ def rdatasets::_index_csv "https://raw.githubusercontent.com/vincentarelbundock/ def rdatasets::_cache_loc "rdatasets_index.csv" .# Load index file -def rdatasets::load_index {:index_str("") data index({,}) packages({,}), +def rdatasets::load_index {:index_str("") data index(:{}) packages(:{}), { rdatasets._cache_loc G :index_str; @@ -44,8 +44,8 @@ def rdatasets::load_index {:index_str("") data index({,}) packages({,}), } -def rdatasets::index {,} -def rdatasets::packages {,} +def rdatasets::index :{} +def rdatasets::packages :{} def rdatasets::load {id::str : rdatasets^ csv^, rdatasets.index :E 0 = { diff --git a/std/shell.aya b/std/shell.aya index 73444255..fd7a534c 100644 --- a/std/shell.aya +++ b/std/shell.aya @@ -56,7 +56,7 @@ def ::cd {{sys.cd} 0:`} def ::mkdir { {sys.mkdir} 0 :` } -.# def ::echo ({(4 hold)x (2 hold)~} {, shell_impl.echo.` :x } .+) +.# def ::echo ({(4 hold)x (2 hold)~} :{ shell_impl.echo.` :x } .+) .#? echo S\n print a string to the console def ::echo {: shell_impl^, diff --git a/std/turtle.aya b/std/turtle.aya index ab301d09..2e4ec5d6 100644 --- a/std/turtle.aya +++ b/std/turtle.aya @@ -8,7 +8,7 @@ Examples: .# Offset nested balls - {, 200:width 200:height} turtle!:t + :{ 200:width 200:height} turtle!:t 10R :# {n, {0.1 t.right n t.fd 2:Z} 100 %} ; .# A small colorful star @@ -28,7 +28,7 @@ color.colors.black :c_black; def turtle::__init__ {params::dict self : canvas^ c_black^ c_white^, .# Default values - {, + :{ 0:x 0:y 0:r @@ -54,7 +54,7 @@ def turtle::__init__ {params::dict self : canvas^ c_black^ c_white^, params.canvas nil = { params.width self.:_w; params.height self.:_h; - {, self._w:width self._h:height "Turtle":name } canvas! self.:_cvs; + :{ self._w:width self._h:height "Turtle":name } canvas! self.:_cvs; } { params.canvas self.:_cvs; self._cvs.width self.:_w; @@ -187,7 +187,7 @@ def turtle::__rpow__ {self val, .# For testing -{, +:{ 100 :width 100 :height ::deg :units diff --git a/std/unit.aya b/std/unit.aya index 712c7857..606a17b6 100644 --- a/std/unit.aya +++ b/std/unit.aya @@ -12,7 +12,7 @@ "3hour 1mph *" => 3mile .} -{, +:{ .# Length @@ -76,7 +76,7 @@ .# Regular Version .# {(1 hold)(\@*\/)}:to; -{, +:{ {(1 hold)({sub super : super_type, super.__type__ :super_type; super ::__type__ .- ; diff --git a/std/viewmat.aya b/std/viewmat.aya index 470a22f7..9d8ed1c4 100644 --- a/std/viewmat.aya +++ b/std/viewmat.aya @@ -8,7 +8,7 @@ def ::viewmat_scaled { data scale : cvs canvas^, .# special case for matrix data :T ::matrix = {data.rows :data;} ? - {, + :{ data E :height; data.[0] E :width; scale :scale; diff --git a/test/base/test_block.aya b/test/base/test_block.aya index 1548a372..ac7280db 100644 --- a/test/base/test_block.aya +++ b/test/base/test_block.aya @@ -15,13 +15,13 @@ { {a b, a b }.haslocals 1 } { {a b : c d, a b }.haslocals 1 } -{ {: a b, }.locals {, 0:a 0:b } } +{ {: a b, }.locals :{ 0:a 0:b } } { {a b, }.haslocals 1 } { {a b$::str,}.args - [ {, ::a:name; ::simple:argtype; } - {, 1:copy; ::b:name; ::str:type; ::typed:argtype; } ] + [ :{ ::a:name; ::simple:argtype; } + :{ 1:copy; ::b:name; ::str:type; ::typed:argtype; } ] } diff --git a/test/base/test_list.aya b/test/base/test_list.aya index 4c424547..178e7357 100644 --- a/test/base/test_list.aya +++ b/test/base/test_list.aya @@ -92,8 +92,8 @@ {[[1 2][4][1 2 3]].makesquare [[1 2 0][4 0 0][1 2 3]] } -{ [{, 1:a } {, 2:b }].dict_flatten {, 1:a 2:b } } -{ [{, 1:a 3:b } {, 2:b }].dict_flatten {, 1:a 2:b } } +{ [:{ 1:a } :{ 2:b }].dict_flatten :{ 1:a 2:b } } +{ [:{ 1:a 3:b } :{ 2:b }].dict_flatten :{ 1:a 2:b } } diff --git a/test/colon_ops.aya b/test/colon_ops.aya index 238f578e..55ec4ed4 100644 --- a/test/colon_ops.aya +++ b/test/colon_ops.aya @@ -8,11 +8,11 @@ { [1 2 3] [1 2] :| [3] } test.test -{ {, } :K [] } test.test +{ :{ } :K [] } test.test .# Test that removing all leaves an empty lise -{ {, 1:a 2:b } :K [::a ::b] :| [] } test.test +{ :{ 1:a 2:b } :K [::a ::b] :| [] } test.test .# Test that the length is 2 -{ {, 1:a 2:b } :K E 2 } test.test +{ :{ 1:a 2:b } :K E 2 } test.test .# Get variables as a dict diff --git a/test/core.aya b/test/core.aya index 86fb4d32..7fcc7b8c 100644 --- a/test/core.aya +++ b/test/core.aya @@ -90,7 +90,7 @@ {"hi" {s::list,s} ~} assert ["hi"] {'C {s::char,s} ~} assert ['C] {1 'C "C" {a::any b::any c::any, a b c} ~} assert [1 'C "C"] -{ {,} {d::dict,d}~} assert [{,}] +{ :{} {d::dict,d}~} assert [:{}] {1 {s::str,} ~} assertfail {[1 2 3] {s::str,} ~} assertfail @@ -105,29 +105,29 @@ {:a(2), 1 ({a: b(a), a b})} assert [1 2] {:a(9), 2 ({a: a(a 1 +), a})} assert [2] -{{: b({,}), b}:x; 1 x.:y; x} assert [{,1:y}] +{{: b(:{}), b}:x; 1 x.:y; x} assert [:{1:y}] .# Dictionaries -{{,}} assert [{,}] -{{,5 "hi" 'C}} assert [{,}] -{{, 5:x}.x} assert [5] -{5 {,}.:x.x} assert [5] -{ {,{,5:x}:x;}.x.x} assert [5] -{ {,5:x} "x" H} assert [1] -{ {,5:x} "y" H} assert [0] +{:{}} assert [:{}] +{:{5 "hi" 'C}} assert [:{}] +{:{ 5:x}.x} assert [5] +{5 :{}.:x.x} assert [5] +{ :{:{5:x}:x;}.x.x} assert [5] +{ :{5:x} "x" H} assert [1] +{ :{5:x} "y" H} assert [0] .# Symbols -{ {, 1:"FOO" } ."FOO" } assert [1] +{ :{ 1:"FOO" } ."FOO" } assert [1] .# Meta dictionaries -{{, 1:a} {, 2:b} :M .a} assert [1] -{{, 1:a} {, 2:b} :M .b} assert [2] -{{, 1:a} {, 2:b 10:a} :M .a} assert [1] -{{, 1:a {, 2:b}:__meta__} .a} assert [1] -{{, 1:a {, 2:b}:__meta__} .b} assert [2] -{{, 1:a {, 2:b 10:a}:__meta__} .a} assert [1] +{:{ 1:a} :{ 2:b} :M .a} assert [1] +{:{ 1:a} :{ 2:b} :M .b} assert [2] +{:{ 1:a} :{ 2:b 10:a} :M .a} assert [1] +{:{ 1:a :{ 2:b}:__meta__} .a} assert [1] +{:{ 1:a :{ 2:b}:__meta__} .b} assert [2] +{:{ 1:a :{ 2:b 10:a}:__meta__} .a} assert [1] .# Lambdas {({1})} assert [1] @@ -160,7 +160,7 @@ 0:a; {100 f} assert [100] - {, 1:a 2:b }:b; + :{ 1:a 2:b }:b; {:b^, b.a b.b b.c}:g; 3 b.:c; 20 b.:b; @@ -172,7 +172,7 @@ .# push self ({:d x y m, - {, 1:x 2:y {1+}:inc }:d; + :{ 1:x 2:y {1+}:inc }:d; {d.x d.y} assert [1 2] {d.y d.inc} assert [3] @@ -197,9 +197,9 @@ {d.foo} assert [3] {10 20 d.bar} assert [10 20 1 2] - {, {other self, other.a self.a + other.b self.b + J}:__add__ }:m; - {, 1:a 2:b m:__meta__ }:x; - {, 3:a 4:b m:__meta__ }:y; + :{ {other self, other.a self.a + other.b self.b + J}:__add__ }:m; + :{ 1:a 2:b m:__meta__ }:x; + :{ 3:a 4:b m:__meta__ }:y; .# if self is not pushed, should have an empty stack { x y + } assertfail @@ -218,7 +218,7 @@ ({:d, .# Create dict with strings - {, 1:x 2:y } :d; + :{ 1:x 2:y } :d; 3 d.:["Hello!"]; 4 d.:["foo bar"]; 5 d.:["var"]; @@ -234,20 +234,20 @@ .# get/set block metadata ({:args, [ - {, + :{ ::a:name; ::simple:argtype; - } {, + } :{ ::num:type; 1:copy; ::b:name; ::typed:argtype; - } {, + } :{ ::str:type; 0:copy; ::c:name; ::typed:argtype; - } {, + } :{ ::any:type; 1:copy; ::d:name; @@ -278,4 +278,4 @@ assert { {a b, a b +} .! P } assert ["{a b +}"] .# type override -{ {, {, ::foo:__type__ }:__meta__ } {x::foo, 1 } ~} assert [1] +{ :{ :{ ::foo:__type__ }:__meta__ } {x::foo, 1 } ~} assert [1] diff --git a/test/dot_ops.aya b/test/dot_ops.aya index f5848f8b..08b356aa 100644 --- a/test/dot_ops.aya +++ b/test/dot_ops.aya @@ -6,20 +6,20 @@ .# TODO: .| locals appears to be a bit broken .{ -{ {: a("hi") b(a), }.locals {, "hi":a {a}:b } } +{ {: a("hi") b(a), }.locals :{ "hi":a {a}:b } } aya> {: a("hi") b(a), } {: b(a) a("hi"),} aya> {: a("hi") b(a), } .locals -{,} +:{} aya> {: a b, }:locals {: b a,} aya> {: a b, }.locals -{, +:{ 0:b; 0:a; } aya> {: a(1) b, }.locals -{, +:{ 0:b; } .} diff --git a/test/filesystem.aya b/test/filesystem.aya index de36d1ea..3cc2e4cd 100644 --- a/test/filesystem.aya +++ b/test/filesystem.aya @@ -77,7 +77,7 @@ import ::image {"dir1/dir2" :(sys.readdir) ["dir3"sep] = 1} test.test .# Create a single pixel image -{, 1:width 1:height [41]:r [164]:g [34]:b }:img; +:{ 1:width 1:height [41]:r [164]:g [34]:b }:img; img "out.png" :(image.write) {"." :(sys.readdir)C ["dir1"sep "hello.txt" "out.png"]C = 1} test.test diff --git a/test/std/test_matrix.aya b/test/std/test_matrix.aya index cbeb7dbc..2ce989b8 100644 --- a/test/std/test_matrix.aya +++ b/test/std/test_matrix.aya @@ -158,7 +158,7 @@ }:test_matrix; -{, +:{ import ::matrix matrix test_matrix diff --git a/test/test.aya b/test/test.aya index 4b45dc53..143bad19 100644 --- a/test/test.aya +++ b/test/test.aya @@ -19,7 +19,7 @@ { "fail".D } assertfail {fname, - {, + :{ "* Running tests '$fname'..." :P "$(:(sys.ad))$fname.aya" :F " Tests complete: '$fname'" :P @@ -61,7 +61,7 @@ "stats" "stack" ] :# {mod, - {, "test/std/test_$mod" load_test }; + :{ "test/std/test_$mod" load_test }; }; .# Import entire standard library diff --git a/test/test_op_overload.aya b/test/test_op_overload.aya index 78225a2d..ac32d240 100644 --- a/test/test_op_overload.aya +++ b/test/test_op_overload.aya @@ -1,12 +1,12 @@ .# This file tests operator overloading features .# For testing modules or other aya code, see base/test.aya -{, +:{ ::vec :__type__; 1 :__pushself__; - {l meta, {, l:l} meta :M}:__new__; + {l meta, :{ l:l} meta :M}:__new__; {self, "<" self.lPB;V; ">" ++}:__str__:__repr__; {o self, o:T ::vec = {o.l} {o} .? self.l + self.M!}:__add__; @@ -78,7 +78,7 @@ {v : vec^, vR vec! } vec.:__range__; "add/radd..." :P -{, +:{ [1 2 3] vec! :v; { v P "< 1 2 3 >" } test.test { 3 v + P "< 4 5 6 >" } test.test @@ -88,7 +88,7 @@ }; "sub/rsub..." :P -{, +:{ [1 2 3] vec! :v; { v P "< 1 2 3 >" } test.test { 3 v - P "< 2 1 0 >" } test.test @@ -99,7 +99,7 @@ }; "mul/rmul..." :P -{, +:{ [1 2 3] vec! :v; { 3 v * P "< 3 6 9 >" } test.test { v 3 * P "< 3 6 9 >" } test.test @@ -109,7 +109,7 @@ }; "div/rdiv..." :P -{, +:{ [2 4 6] vec! :v; { 24 v / P "< 12 6 4 >" } test.test { v 2 / P "< 1 2 3 >" } test.test @@ -121,7 +121,7 @@ "mod/rmod..." :P -{, +:{ [1 2 3] vec! :v; { 2 v :% P "< 0 0 2 >" } test.test { v 2 :% P "< 1 0 1 >" } test.test @@ -132,7 +132,7 @@ "idiv/rdiv..." :P -{, +:{ [1 2 3] vec! :v; { 2 v .% P "< 2 1 0 >" } test.test { v 2 .% P "< 0 1 1 >" } test.test @@ -142,35 +142,35 @@ }; "lt..." :P -{, +:{ [1 2 3] vec! :v; { 3 v < P "< 0 0 0 >" } test.test { [1 2 3] v < P "[ < 0 1 1 > < 0 0 1 > < 0 0 0 > ]" } test.test }; "gt..." :P -{, +:{ [1 2 3] vec! :v; { 3 v > P "< 1 1 0 >" } test.test { [1 2 3] v > P "[ < 0 0 0 > < 1 0 0 > < 1 1 0 > ]" } test.test }; "leq..." :P -{, +:{ [1 2 3] vec! :v; { 3 v :< P "< 0 0 1 >" } test.test { [1 2 3] v :< P "[ < 1 1 1 > < 0 1 1 > < 0 0 1 > ]" } test.test }; "geq..." :P -{, +:{ [1 2 3] vec! :v; { 3 v :> P "< 1 1 1 >" } test.test { [1 2 3] v :> P "[ < 1 0 0 > < 1 1 0 > < 1 1 1 > ]" } test.test }; "eq..." :P -{, +:{ [1 2 3] vec! :v; { (v v =) 1 } test.test { (v v1+ =) 0 } test.test @@ -179,63 +179,63 @@ "reverse..." :P -{, +:{ [1 2 3] vec! :v; { v U P "< 3 2 1 >" } test.test }; "negate..." :P -{, +:{ [1 2 3] vec! :v; { v T P "< -1 -2 -3 >" } test.test }; "sort..." :P -{, +:{ { [6 7 4 5 3] vec! :v P "< 6 7 4 5 3 >" } test.test { v C P "< 3 4 5 6 7 >" } test.test }; "inc..." :P -{, +:{ [1 2 3] vec! :v; { v BB P "< 3 4 5 >" } test.test }; "dec..." :P -{, +:{ [1 2 3] vec! :v; { v VV P "< -1 0 1 >" } test.test }; "len..." :P -{, +:{ [1 2 3] vec! :v; { v E 3 } test.test }; "range..." :P -{, +:{ {3 vecR P "< 1 2 3 >" } test.test {[3 6] vec R P "< 3 4 5 6 >" } test.test }; "random..." :P -{, +:{ [] vec! :v; { 3 v Q .__len__ 3 } test.test }; "each..." :P -{, +:{ [1 2 3] vec! :v; { v :# {1+} P "< 2 3 4 >" } test.test }; "math..." :P -{, +:{ [0 1] vec! :v; { v M! P "< 1 1 >" } test.test { v Ms P "< 0 .84147098 >" } test.test @@ -246,7 +246,7 @@ { v MT P "< 0 .78539816 >" } test.test }; -{, +:{ [1 2] vec! :v; { v Ml P "< 0 .69314718 >" } test.test { v ML P "< 0 .30103 >" } test.test @@ -254,33 +254,33 @@ { v .^ P "< 1 1.41421356 >" } test.test }; -{, +:{ [-2 1 0 -3.4] vec! :v; { v .| P "< 2 1 0 3.4 >" } test.test { v .! P "< -1 1 0 -1 >" } test.test }; -{, +:{ [:2r3 :2z 2] vec! :v; { v Md .l #:T [::num ::num ::num] } test.test }; "head/tail..." :P -{, +:{ [1 2 3 4 5] vec! :v; { v 3 .> P "< 3 4 5 >" } test.test { v 3 .< P "< 1 2 3 >" } test.test }; "getindex..." :P -{, +:{ [1 2 3 4 5] vec! :v; { v.[0] 1 } test.test { v.[-1] 5 } test.test }; "setindex..." :P -{, +:{ [1 2 3 4 5] vec! :v; { 99 v.:[2] P "< 1 2 99 4 5 >" } test.test 0:i; @@ -288,7 +288,7 @@ }; "bool..." :P -{, +:{ [1 2 3 4 5] vec! :v; { v 't 'f .? 't } test.test [ ] vec! :v; diff --git a/test/unicode.aya b/test/unicode.aya index 927d2e41..2b71b28f 100644 --- a/test/unicode.aya +++ b/test/unicode.aya @@ -1,18 +1,18 @@ [ -{ {, 1:¥}.¥ 1 } +{ :{ 1:¥}.¥ 1 } { 1 {¥,¥}~ 1 } { {:¥(10), ¥ }~ 10 } { {:¥(10), {:¥^, ¥ }}~ ~ 10 } { {: ¥(1) §(2), [ ¥§ ] }~ [1 2] } -{ 1 ::M+ {,} :D ."M+" 1 } -{ 1 ::.+ {,} :D .".+" 1 } -{ 1 :::+ {,} :D .":+" 1 } +{ 1 ::M+ :{} :D ."M+" 1 } +{ 1 ::.+ :{} :D .".+" 1 } +{ 1 :::+ :{} :D .":+" 1 } {:__cdict__, - {, + :{ 1:x 2:"@" 3:"3" From ec73a330eea87db397f6353cf75547141637a3f2 Mon Sep 17 00:00:00 2001 From: npgit Date: Tue, 17 Dec 2024 20:13:47 -0500 Subject: [PATCH 3/3] New dict literals now support headers with the same syntax as blocks --- base/block.aya | 16 -- examples/quicksort.aya | 2 +- .../instruction/DictLiteralInstruction.java | 99 ++++---- .../EmptyDictLiteralInstruction.java | 3 - src/aya/obj/block/StaticBlock.java | 8 + src/aya/parser/HeaderUtils.java | 212 +++++++++++++++++ src/aya/parser/tokens/BlockToken.java | 218 +----------------- src/aya/parser/tokens/CollectionToken.java | 4 + src/aya/parser/tokens/DictToken.java | 44 ++-- std/matrix.aya | 2 +- std/mp.aya | 4 - 11 files changed, 303 insertions(+), 309 deletions(-) create mode 100644 src/aya/parser/HeaderUtils.java diff --git a/base/block.aya b/base/block.aya index 7d0c85d8..e064e3b5 100644 --- a/base/block.aya +++ b/base/block.aya @@ -72,22 +72,6 @@ .# Utility Functions .##################### - - .# ::list _capture_vars\n given a list of symbols, return a dict with each symbol and it's assignment - .{ Example: - aya> {1 +}:a 2:b - {1 +} 2 - aya> [::a ::b].capture_vars - :{ - {1 +}:a; - 2:b; - } - aya> [::a ::b ::c].capture_vars - ERROR: Variable c not found - .} - { :{1, :# {$~\:=} } }:_capture_vars; - - .#? ::block .op\n return the block (allows use of (::sym or ::block) .op without type checking {}:op; diff --git a/examples/quicksort.aya b/examples/quicksort.aya index a06e8f10..a8bf73ef 100644 --- a/examples/quicksort.aya +++ b/examples/quicksort.aya @@ -42,7 +42,7 @@ lst qs :P {.E1> {$\; :&V$@\< @\ :&#! @:&@.i \@.i qss @@qss JJ} ?}:qss; .# Stack only version with no global vars -.# {.E1> {$\; :&V$@\< @\ :&#! @:&@.i \@.i _ @@_ JJ} ?} :{1, :_} :+ +.# {.E1> {$\; :&V$@\< @\ :&#! @:&@.i \@.i _ @@_ JJ} ?} :{_,} :+ .# Quicksort benchmark and example output .# aya> 10 R :# {; [100000,;.Q] {qs;}.time} :& .E \W\/ diff --git a/src/aya/instruction/DictLiteralInstruction.java b/src/aya/instruction/DictLiteralInstruction.java index 3d5bb384..bfc4628d 100644 --- a/src/aya/instruction/DictLiteralInstruction.java +++ b/src/aya/instruction/DictLiteralInstruction.java @@ -1,16 +1,16 @@ package aya.instruction; -import java.util.LinkedList; -import java.util.Queue; +import java.util.HashMap; import aya.ReprStream; -import aya.eval.ExecutionContext; import aya.eval.BlockEvaluator; -import aya.obj.Obj; +import aya.exceptions.runtime.EmptyStackError; import aya.obj.block.BlockUtils; import aya.obj.block.StaticBlock; import aya.obj.dict.Dict; +import aya.obj.symbol.Symbol; import aya.parser.SourceStringRef; +import aya.variable.VariableData; /** DictFactories sit on the instruction stack. When evoked, they generate a dict * given the current scope of variables @@ -20,65 +20,72 @@ public class DictLiteralInstruction extends Instruction { StaticBlock _block; - private int num_captures; + HashMap _defaults; public DictLiteralInstruction(SourceStringRef source, StaticBlock b) { - super(source); - this._block = b; - this.num_captures = 0; + this(source, b, null); } - public DictLiteralInstruction(SourceStringRef source, StaticBlock b, int num_captures) { + public DictLiteralInstruction(SourceStringRef source, StaticBlock b, HashMap defaults) { super(source); this._block = b; - this.num_captures = num_captures; - } - - public int numCaptures() { - return num_captures; + this._defaults = defaults; } - - /** Run the dict, collect variables, return the Dict object */ - public Dict getDict(ExecutionContext context, Queue q) { - //Add the variable set to the stack - context.getVars().add(new Dict(), true); + + @Override + public void execute(BlockEvaluator b) { + final VariableData vars = b.getContext().getVars(); + + // Add the variable set to the stack, true: capture all assignments + Dict dict_scope = new Dict(); + vars.add(dict_scope, true); - //Run the blockEvaluator - BlockEvaluator evaluator = context.createEvaluator(); - if (q != null) { - while (!q.isEmpty()) { - evaluator.push(q.poll()); + // If there are defaults, add them to the dict scope + if (_defaults != null) { + for (Symbol var : _defaults.keySet()) { + BlockEvaluator evaluator = b.getContext().createEvaluator(); + evaluator.dump(_defaults.get(var)); + evaluator.eval(); + dict_scope.set(var, evaluator.pop()); } } - evaluator.dump(_block); - evaluator.eval(); + + // Run block in an isolated evaluator so we can copy the variables once the block is finished + BlockEvaluator evaluator = b.getContext().createEvaluator(); + + final int num_args = _block.getNumArgs(); + final boolean has_locals = _block.hasLocals(); - //Retrieve the Dict - return context.getVars().popGet(); - } - - @Override - public void execute(BlockEvaluator b) { - Queue q = null; - int n = this.numCaptures(); - if (n > 0) { - q = new LinkedList(); - for (int i = 0; i < n; i++) { - q.add(b.pop()); + // Copy stack args into evaluator (preserve order) + if (num_args > 0) { + if (b.getStack().size() < num_args) { + throw new EmptyStackError("Empty stack at dict literal"); } + final int offset = b.getStack().size() - 1; + for (int i = num_args-1; i >= 0; i--) evaluator.push(b.getStack().get(offset - i)); + for (int i = 0; i < num_args; i++) b.pop(); } - b.push(this.getDict(b.getContext(), q)); + evaluator.dump(_block); + + // If we have locals, we will want to pull the data out if it before they are popped + // so we remove the instruction to pop the variables, we will do it ourselves below + if (has_locals) evaluator.getInstructions().getInstrucionList().remove(0); + + evaluator.eval(); + + if (has_locals) { + Dict block_locals = vars.popGet(); + dict_scope.update(block_locals); + } + + // Pop the dict scope and add it to the stack + b.push(vars.popGet()); // popGet returns dict_scope } @Override public ReprStream repr(ReprStream stream) { - if (num_captures == 0) { - stream.print(":{"); - } else { - stream.print("{" + num_captures + ","); - } - BlockUtils.repr(stream, _block, false, null); - stream.print("}"); + stream.print(":"); + BlockUtils.repr(stream, _block, true, null); return stream; } } diff --git a/src/aya/instruction/EmptyDictLiteralInstruction.java b/src/aya/instruction/EmptyDictLiteralInstruction.java index 4b10f074..cc132d2a 100644 --- a/src/aya/instruction/EmptyDictLiteralInstruction.java +++ b/src/aya/instruction/EmptyDictLiteralInstruction.java @@ -19,9 +19,6 @@ protected EmptyDictLiteralInstruction() { super(null, StaticBlock.EMPTY); } - @Override - public int numCaptures() { return 0; } - public Dict getDict(ExecutionContext context, Queue q) { return new Dict(); } diff --git a/src/aya/obj/block/StaticBlock.java b/src/aya/obj/block/StaticBlock.java index f9c308c5..528cb5fe 100644 --- a/src/aya/obj/block/StaticBlock.java +++ b/src/aya/obj/block/StaticBlock.java @@ -58,6 +58,14 @@ public boolean hasLocals() { return _locals != null; } + public int getNumArgs() { + if (_args == null) { + return 0; + } else { + return _args.size(); + } + } + ////////////////////// // Used By BlockOps // ////////////////////// diff --git a/src/aya/parser/HeaderUtils.java b/src/aya/parser/HeaderUtils.java new file mode 100644 index 00000000..1c76c0b3 --- /dev/null +++ b/src/aya/parser/HeaderUtils.java @@ -0,0 +1,212 @@ +package aya.parser; + + +import java.util.ArrayList; +import java.util.HashMap; + +import aya.exceptions.parser.EndOfInputError; +import aya.exceptions.parser.ParserException; +import aya.exceptions.parser.SyntaxError; +import aya.instruction.Instruction; +import aya.instruction.variable.QuoteGetVariableInstruction; +import aya.instruction.variable.assignment.Assignment; +import aya.instruction.variable.assignment.SimpleAssignment; +import aya.instruction.variable.assignment.TypedAssignment; +import aya.instruction.variable.assignment.UnpackAssignment; +import aya.obj.block.BlockUtils; +import aya.obj.block.StaticBlock; +import aya.obj.dict.Dict; +import aya.obj.number.Num; +import aya.obj.symbol.Symbol; +import aya.parser.token.TokenQueue; +import aya.parser.tokens.LambdaToken; +import aya.parser.tokens.ListToken; +import aya.parser.tokens.OperatorToken; +import aya.parser.tokens.SymbolToken; +import aya.parser.tokens.Token; +import aya.parser.tokens.VarToken; +import aya.util.Pair; +import aya.util.Triple; + +public class HeaderUtils { + + // args, locals, captures + public static Triple, Dict, HashMap> generateBlockHeader(TokenQueue tokens) throws ParserException { + Pair split_tokens = splitAtColon(tokens); + TokenQueue arg_tokens = split_tokens.first(); + TokenQueue locals_and_captures_tokens = split_tokens.second(); + + // Args + ArrayList args = generateBlockHeaderArgs(arg_tokens); + + // Locals & Captures + Pair> locals_and_captures = generateBlockHeaderDefaults(locals_and_captures_tokens); + Dict locals = locals_and_captures.first(); + HashMap captures = locals_and_captures.second(); + + // Null checks + if (args.size() == 0) args = null; + if (locals.size() == 0) locals = null; + if (captures.size() == 0) captures = null; + + return new Triple, Dict, HashMap>(args, locals, captures); + } + + private static ArrayList generateBlockHeaderArgs(TokenQueue tokens) throws ParserException { + ArrayList out = new ArrayList(); + while (tokens.hasNext()) { + Assignment arg = nextArg(tokens); + out.add(arg); + } + return out; + } + + private static Assignment nextArg(TokenQueue tokens) throws EndOfInputError, SyntaxError { + Token current = tokens.next(); + if (current.isa(Token.VAR)) { + VarToken var = (VarToken)current; + boolean copy = false; + Symbol arg_type = null; + + // Copy? + if (tokens.hasNext() && tokens.peek().isa(Token.OP) && tokens.peek().getData().equals("$")) { + tokens.next(); // Discard $ + copy = true; + } + + // Type annotation? + if (tokens.hasNext() && tokens.peek().isa(Token.SYMBOL)) { + SymbolToken sym_token = (SymbolToken)tokens.next(); + arg_type = sym_token.getSymbol(); + } + + if (copy || arg_type != null) { + return new TypedAssignment(var.getSourceStringRef(), var.getSymbol(), arg_type, copy); + } else { + return new SimpleAssignment(var.getSourceStringRef(), var.getSymbol()); + } + } else if (current.isa(Token.LIST)) { + ListToken unpack = (ListToken)current; + TokenQueue tq = new TokenQueue(unpack.getCol()); + ArrayList args = new ArrayList(); + Symbol catchall = null; + while (tq.hasNext()) { + // Catch-all + if (tq.peek().isa(Token.COLON)) { + Token colon = tq.next(); // colon + if (tq.hasNext() && tq.peek().isa(Token.VAR)) { + Token var = tq.next(); + catchall = ((VarToken)var).getSymbol(); + } else { + throw new SyntaxError("Expected varname after catchall assignment", colon.getSourceStringRef()); + } + + if (tq.hasNext()) { + throw new SyntaxError("Catch-all name must be last", current.getSourceStringRef()); + } + } else { + Assignment a = nextArg(tq); + boolean slurp = false; + if (tq.hasNext() && tq.peek().isa(Token.OP) && tq.peek().getData().equals("~")) { + slurp = true; + tq.next(); // Skip ~ + } + + args.add(new UnpackAssignment.Arg(a, slurp)); + } + } + + if (args.size() == 0) { + throw new SyntaxError("Unpack args must contain at least one element", current.getSourceStringRef()); + } else { + UnpackAssignment ua = UnpackAssignment.fromArgList(args, catchall, current.getSourceStringRef()); + return ua; + } + } else { + throw new SyntaxError("All arguments should follow the format name[$][::type]", current.getSourceStringRef()); + } + } + + /** Assumes args have already been set + * @param captures + * @throws ParserException */ + private static Pair> generateBlockHeaderDefaults(TokenQueue tokens) throws ParserException { + Dict locals = new Dict(); + HashMap captures = new HashMap(); + + while (tokens.hasNext()) { + Token current = tokens.next(); + if (current.isa(Token.VAR)) { + VarToken var = (VarToken)current; + if (!tokens.hasNext() || tokens.peek().isa(Token.VAR)) { + locals.set(var.getSymbol(), Num.ZERO); + } else if (tokens.peek().isa(Token.LAMBDA)){ + LambdaToken lambda = (LambdaToken)tokens.next(); + captures.put(var.getSymbol(), BlockUtils.fromIS(lambda.generateInstructionsForFirst())); + } else if (tokens.peek().isa(Token.OP)) { + OperatorToken opt = (OperatorToken)tokens.next(); + if (opt.getData().equals("^")) { + Instruction i = new QuoteGetVariableInstruction(current.getSourceStringRef(), var.getSymbol()); + StaticBlock b = BlockUtils.makeBlockWithSingleInstruction(i); + captures.put(var.getSymbol(), b); + } else { + generateBlockHeaderDefaultsError(current.getSourceStringRef()); + } + } else { + generateBlockHeaderDefaultsError(current.getSourceStringRef()); + } + } else { + generateBlockHeaderDefaultsError(current.getSourceStringRef()); + } + } + + return new Pair>(locals, captures); + } + + private static void generateBlockHeaderDefaultsError(SourceStringRef source) throws SyntaxError { + throw new SyntaxError("All variable initializers should follow the format name()", source); + } + + + + /** Split a single tokenQueue into two at the location of the colon + * t1 contains all tokens before the colon + * t2 contains all tokens after the colon + * both may be empty if there was nothing before/after the colon + * the colon is not included in any + * @param tokens + * @return + * @throws SyntaxError + */ + private static Pair splitAtColon(TokenQueue tokens) throws SyntaxError { + ArrayList ts = tokens.getArrayList(); + int colons = 0; + int colon_index = 0; + for (int i = 0; i < ts.size(); i++) { + if (ts.get(i).isa(Token.COLON)) { + colon_index = i; + colons++; + } + } + + if (colons == 0) { + return new Pair(tokens, new TokenQueue()); + } else if (colons > 1) { + throw new SyntaxError("Expected only one colon (:) token in blockEvaluator header", tokens.peek().getSourceStringRef()); + } else { + ArrayList t1 = new ArrayList(colon_index); + ArrayList t2 = new ArrayList(ts.size()-colon_index); + for (int i = 0; i < colon_index; i++) { + t1.add(ts.get(i)); + } + // colon_index+1 skip the colon itself + for (int i = colon_index+1; i < ts.size(); i++) { + t2.add(ts.get(i)); + } + + return new Pair(new TokenQueue(t1), + new TokenQueue(t2)); + } + } + +} diff --git a/src/aya/parser/tokens/BlockToken.java b/src/aya/parser/tokens/BlockToken.java index b851bccf..d125178a 100644 --- a/src/aya/parser/tokens/BlockToken.java +++ b/src/aya/parser/tokens/BlockToken.java @@ -3,27 +3,22 @@ import java.util.ArrayList; import java.util.HashMap; -import aya.exceptions.parser.EndOfInputError; import aya.exceptions.parser.ParserException; import aya.exceptions.parser.SyntaxError; import aya.instruction.BlockLiteralInstruction; import aya.instruction.Instruction; import aya.instruction.InstructionStack; -import aya.instruction.variable.QuoteGetVariableInstruction; import aya.instruction.variable.assignment.Assignment; -import aya.instruction.variable.assignment.SimpleAssignment; -import aya.instruction.variable.assignment.TypedAssignment; -import aya.instruction.variable.assignment.UnpackAssignment; import aya.obj.Obj; import aya.obj.block.BlockUtils; import aya.obj.block.StaticBlock; import aya.obj.dict.Dict; import aya.obj.number.Num; import aya.obj.symbol.Symbol; +import aya.parser.HeaderUtils; import aya.parser.Parser; import aya.parser.SourceStringRef; import aya.parser.token.TokenQueue; -import aya.util.Pair; import aya.util.Triple; public class BlockToken extends CollectionToken { @@ -48,41 +43,14 @@ public Instruction getInstruction() throws ParserException { if (blockData.size() == 2) { //Empty header, dict literal if (!header.hasNext()) { + // Eventually this may be used to specify that a block has locals + // For now it is an error to help transition from old dict literals throw new SyntaxError("Block cannot have an empty header", source); - //InstructionStack instructions = Parser.generate(blockData.get(1)); - //if (instructions.size() == 0) { - // return EmptyDictLiteralInstruction.INSTANCE; - //} else { - // return new DictLiteralInstruction(this.getSourceStringRef(), BlockUtils.fromIS(instructions)); - //} - } - // Single number in header, create a dict factory with a capture - else if (header.size() == 1 && header.peek() instanceof NumberToken) { - throw new SyntaxError("Block cannot have a number in header", source); - /* - NumberToken nt = (NumberToken)header.peek(); - int n = 0; - try { - n = nt.numValue().toInt(); - } catch (NumberFormatException e) { - throw new SyntaxError(nt + " is not a valid number in the blockEvaluator header", nt.getSourceStringRef()); - } - - if (n < 1) { - throw new SyntaxError("Cannot capture less than 1 elements from outer stack in a dict literal", nt.getSourceStringRef()); - } - InstructionStack instructions = Parser.generate(blockData.get(1)); - if (n == 0 && instructions.isEmpty()) { - return EmptyDictLiteralInstruction.INSTANCE; - } else { - return new DictLiteralInstruction(this.getSourceStringRef(), BlockUtils.fromIS(instructions), n); - } - */ } //Non-empty header, args and local variables else { InstructionStack main_instructions = Parser.generate(blockData.get(1)); - Triple, Dict, HashMap> p = generateBlockHeader(blockData.get(0)); + Triple, Dict, HashMap> p = HeaderUtils.generateBlockHeader(blockData.get(0)); StaticBlock blk = BlockUtils.fromIS(main_instructions, p.second(), p.first()); return new BlockLiteralInstruction(this.getSourceStringRef(), blk, p.third()); } @@ -92,184 +60,6 @@ else if (header.size() == 1 && header.peek() instanceof NumberToken) { } } - // args, locals, captures - private Triple, Dict, HashMap> generateBlockHeader(TokenQueue tokens) throws ParserException { - Pair split_tokens = splitAtColon(tokens); - TokenQueue arg_tokens = split_tokens.first(); - TokenQueue locals_and_captures_tokens = split_tokens.second(); - - // Args - ArrayList args = generateBlockHeaderArgs(arg_tokens); - - // Locals & Captures - Pair> locals_and_captures = generateBlockHeaderDefaults(locals_and_captures_tokens); - Dict locals = locals_and_captures.first(); - HashMap captures = locals_and_captures.second(); - - // Null checks - if (args.size() == 0) args = null; - if (locals.size() == 0) locals = null; - if (captures.size() == 0) captures = null; - - return new Triple, Dict, HashMap>(args, locals, captures); - } - - private static ArrayList generateBlockHeaderArgs(TokenQueue tokens) throws ParserException { - ArrayList out = new ArrayList(); - while (tokens.hasNext()) { - Assignment arg = nextArg(tokens); - out.add(arg); - } - return out; - } - - private static Assignment nextArg(TokenQueue tokens) throws EndOfInputError, SyntaxError { - Token current = tokens.next(); - if (current.isa(Token.VAR)) { - VarToken var = (VarToken)current; - boolean copy = false; - Symbol arg_type = null; - - // Copy? - if (tokens.hasNext() && tokens.peek().isa(Token.OP) && tokens.peek().data.equals("$")) { - tokens.next(); // Discard $ - copy = true; - } - - // Type annotation? - if (tokens.hasNext() && tokens.peek().isa(Token.SYMBOL)) { - SymbolToken sym_token = (SymbolToken)tokens.next(); - arg_type = sym_token.getSymbol(); - } - - if (copy || arg_type != null) { - return new TypedAssignment(var.getSourceStringRef(), var.getSymbol(), arg_type, copy); - } else { - return new SimpleAssignment(var.getSourceStringRef(), var.getSymbol()); - } - } else if (current.isa(Token.LIST)) { - ListToken unpack = (ListToken)current; - TokenQueue tq = new TokenQueue(unpack.col); - ArrayList args = new ArrayList(); - Symbol catchall = null; - while (tq.hasNext()) { - // Catch-all - if (tq.peek().isa(Token.COLON)) { - Token colon = tq.next(); // colon - if (tq.hasNext() && tq.peek().isa(Token.VAR)) { - Token var = tq.next(); - catchall = ((VarToken)var).getSymbol(); - } else { - throw new SyntaxError("Expected varname after catchall assignment", colon.getSourceStringRef()); - } - - if (tq.hasNext()) { - throw new SyntaxError("Catch-all name must be last", current.getSourceStringRef()); - } - } else { - Assignment a = nextArg(tq); - boolean slurp = false; - if (tq.hasNext() && tq.peek().isa(Token.OP) && tq.peek().data.equals("~")) { - slurp = true; - tq.next(); // Skip ~ - } - - args.add(new UnpackAssignment.Arg(a, slurp)); - } - } - - if (args.size() == 0) { - throw new SyntaxError("Unpack args must contain at least one element", current.getSourceStringRef()); - } else { - UnpackAssignment ua = UnpackAssignment.fromArgList(args, catchall, current.getSourceStringRef()); - return ua; - } - } else { - throw new SyntaxError("All arguments should follow the format name[$][::type]", current.getSourceStringRef()); - } - } - - /** Assumes args have already been set - * @param captures - * @throws ParserException */ - private static Pair> generateBlockHeaderDefaults(TokenQueue tokens) throws ParserException { - Dict locals = new Dict(); - HashMap captures = new HashMap(); - - while (tokens.hasNext()) { - Token current = tokens.next(); - if (current.isa(VAR)) { - VarToken var = (VarToken)current; - if (!tokens.hasNext() || tokens.peek().isa(Token.VAR)) { - locals.set(var.getSymbol(), Num.ZERO); - } else if (tokens.peek().isa(Token.LAMBDA)){ - LambdaToken lambda = (LambdaToken)tokens.next(); - captures.put(var.getSymbol(), BlockUtils.fromIS(lambda.generateInstructionsForFirst())); - } else if (tokens.peek().isa(Token.OP)) { - OperatorToken opt = (OperatorToken)tokens.next(); - if (opt.data.equals("^")) { - Instruction i = new QuoteGetVariableInstruction(current.getSourceStringRef(), var.getSymbol()); - StaticBlock b = BlockUtils.makeBlockWithSingleInstruction(i); - captures.put(var.getSymbol(), b); - } else { - generateBlockHeaderDefaultsError(current.getSourceStringRef()); - } - } else { - generateBlockHeaderDefaultsError(current.getSourceStringRef()); - } - } else { - generateBlockHeaderDefaultsError(current.getSourceStringRef()); - } - } - - return new Pair>(locals, captures); - } - - private static void generateBlockHeaderDefaultsError(SourceStringRef source) throws SyntaxError { - throw new SyntaxError("All variable initializers should follow the format name()", source); - } - - - - /** Split a single tokenQueue into two at the location of the colon - * t1 contains all tokens before the colon - * t2 contains all tokens after the colon - * both may be empty if there was nothing before/after the colon - * the colon is not included in any - * @param tokens - * @return - * @throws SyntaxError - */ - private static Pair splitAtColon(TokenQueue tokens) throws SyntaxError { - ArrayList ts = tokens.getArrayList(); - int colons = 0; - int colon_index = 0; - for (int i = 0; i < ts.size(); i++) { - if (ts.get(i).isa(Token.COLON)) { - colon_index = i; - colons++; - } - } - - if (colons == 0) { - return new Pair(tokens, new TokenQueue()); - } else if (colons > 1) { - throw new SyntaxError("Expected only one colon (:) token in blockEvaluator header", tokens.peek().getSourceStringRef()); - } else { - ArrayList t1 = new ArrayList(colon_index); - ArrayList t2 = new ArrayList(ts.size()-colon_index); - for (int i = 0; i < colon_index; i++) { - t1.add(ts.get(i)); - } - // colon_index+1 skip the colon itself - for (int i = colon_index+1; i < ts.size(); i++) { - t2.add(ts.get(i)); - } - - return new Pair(new TokenQueue(t1), - new TokenQueue(t2)); - } - } @Override diff --git a/src/aya/parser/tokens/CollectionToken.java b/src/aya/parser/tokens/CollectionToken.java index 97a584ef..a491c7b9 100644 --- a/src/aya/parser/tokens/CollectionToken.java +++ b/src/aya/parser/tokens/CollectionToken.java @@ -13,6 +13,10 @@ public CollectionToken(int type, String data, ArrayList col, SourceString this.col = col; } + public ArrayList getCol() { + return col; + } + /** Splits a list of tokens wherever a comma is */ protected static ArrayList splitCommas(ArrayList tokens) { ArrayList out = new ArrayList(); diff --git a/src/aya/parser/tokens/DictToken.java b/src/aya/parser/tokens/DictToken.java index cbbb62e0..72f40e49 100644 --- a/src/aya/parser/tokens/DictToken.java +++ b/src/aya/parser/tokens/DictToken.java @@ -1,6 +1,7 @@ package aya.parser.tokens; import java.util.ArrayList; +import java.util.HashMap; import aya.exceptions.parser.ParserException; import aya.exceptions.parser.SyntaxError; @@ -8,10 +9,16 @@ import aya.instruction.EmptyDictLiteralInstruction; import aya.instruction.Instruction; import aya.instruction.InstructionStack; +import aya.instruction.variable.assignment.Assignment; import aya.obj.block.BlockUtils; +import aya.obj.block.StaticBlock; +import aya.obj.dict.Dict; +import aya.obj.symbol.Symbol; +import aya.parser.HeaderUtils; import aya.parser.Parser; import aya.parser.SourceStringRef; import aya.parser.token.TokenQueue; +import aya.util.Triple; public class DictToken extends CollectionToken { @@ -24,43 +31,32 @@ public Instruction getInstruction() throws ParserException { //Split Tokens where there are commas ArrayList blockData = splitCommas(col); + // No header, normal dict literal if (blockData.size() == 1) { InstructionStack instructions = Parser.generate(blockData.get(0)); + + // Optimization for empty dict literal if (instructions.size() == 0) { return EmptyDictLiteralInstruction.INSTANCE; } else { return new DictLiteralInstruction(this.getSourceStringRef(), BlockUtils.fromIS(instructions)); } + } else if (blockData.size() == 2) { TokenQueue header = blockData.get(0); - - // Single number in header, create a dict factory with a capture - if (header.size() == 1 && header.peek() instanceof NumberToken) { - - NumberToken nt = (NumberToken)header.peek(); - int n = 0; - try { - n = nt.numValue().toInt(); - } catch (NumberFormatException e) { - throw new SyntaxError(nt + " is not a valid number in the blockEvaluator header", nt.getSourceStringRef()); - } - - if (n < 1) { - throw new SyntaxError("Cannot capture less than 1 elements from outer stack in a dict literal", nt.getSourceStringRef()); - } - InstructionStack instructions = Parser.generate(blockData.get(1)); - if (n == 0 && instructions.isEmpty()) { - return EmptyDictLiteralInstruction.INSTANCE; - } else { - return new DictLiteralInstruction(this.getSourceStringRef(), BlockUtils.fromIS(instructions), n); - } + + if (header.size() > 0) { + InstructionStack main_instructions = Parser.generate(blockData.get(1)); + Triple, Dict, HashMap> p = HeaderUtils.generateBlockHeader(blockData.get(0)); + StaticBlock blk = BlockUtils.fromIS(main_instructions, p.second(), p.first()); + return new DictLiteralInstruction(this.getSourceStringRef(), blk, p.third()); } else { - throw new SyntaxError("dict headers not supported (yet)", source); + throw new SyntaxError("Empty header not allowed in dict literal", source); } - } else { - throw new SyntaxError("Dict headers not supported (yet)", source); + throw new SyntaxError("Dict literal has too many parts", source); } + } @Override diff --git a/std/matrix.aya b/std/matrix.aya index cc21d9d5..1218bddd 100644 --- a/std/matrix.aya +++ b/std/matrix.aya @@ -23,7 +23,7 @@ def matrix::__init__ {input::list self, .# Use this instead of the constructor to avoid .# validating the list def matrix::_new {matrix, - :{1, :rows} matrix :M + :{rows,} matrix :M } .{ Example: diff --git a/std/mp.aya b/std/mp.aya index 92187e5c..35d113d3 100644 --- a/std/mp.aya +++ b/std/mp.aya @@ -5,10 +5,6 @@ module mp export ::mp -.#? ::list mp.capture_vars\n given a list of symbols, return a dict with each symbol and -def mp::capture_vars ( {}.M._capture_vars.` ) - - .#? ::list mp.merge\n Convert a list of blocks into a single block def mp::merge { #.op .*