#context_scope {
auto(size);
- #insert body;
+ #unquote body;
}
return 0;
#context_scope {
auto();
- #insert body;
+ #unquote body;
}
return 0;
}
-// Represents a code block. Not constructable outside of using a '#code' directive.
+// Represents a code block. Not constructable outside of using a '#quote' directive.
Code :: struct {_:i32;}
},
macro (arr: [] $T, $cmp: Code) -> bool {
- for it: arr do if #insert cmp do return true;
+ for it: arr do if #unquote cmp do return true;
return false;
}
}
map :: #match {
macro (arr: [] $T, f: (^T) -> void) do for ^it: arr do f(it);,
macro (arr: [] $T, f: (T) -> T) do for ^it: arr do *it = f(*it);,
- macro (arr: [] $T, body: Code) do for ^it: arr do #insert body;,
+ macro (arr: [] $T, body: Code) do for ^it: arr do #unquote body;,
macro (arr: [] $T, data: $R, f: (^T, R) -> void) do for ^it: arr do f(it, data);,
macro (arr: [] $T, data: $R, f: (T, R) -> T) do for ^it: arr do *it = f(*it, data);,
}
for bucket_index: bucket.count {
it := ^bucket.data[bucket_index];
- #insert body;
+ #unquote body;
}
}
}
take_one :: take_one
cont: bool;
- (#insert dest), cont = take_one(it);
+ (#unquote dest), cont = take_one(it);
return !cont;
}
thread_function :: (__data: ^Thread_Data, $body: Code) {
thread_data := __data.data;
for #no_close *__data.iter {
- #insert body;
+ #unquote body;
}
}
}
lr := lookup_(map, key);
if lr.entry_index >= 0 {
it := ^map.entries[lr.entry_index].value;
- #insert body;
+ #unquote body;
}
}
tcp_server_handle_events :: macro (server: ^TCP_Server, handler: Code) {
while server->pulse() {
- for server->get_events() do switch it.kind do #insert handler;
+ for server->get_events() do switch it.kind do #unquote handler;
}
}
scoped_mutex :: scoped_mutex;
scoped_mutex(m);
- #insert body;
+ #unquote body;
return 0;
}
This type represents any value. It does this by using a data pointer and a type expression. Using the `builtin.type_info` package, you can introspect that type expression to retrieve data about the type, and from there reconstruct how to use the data pointer. See `conv.onyx` for how this works with `printf`.
- `Code` -
-This is a dummy type that represents the type of a `#code {}` block. It is used when passing code around to macros or procedures, i.e. `f :: macro (body: Code)`
\ No newline at end of file
+This is a dummy type that represents the type of a `#unquote {}` block. It is used when passing code around to macros or procedures, i.e. `f :: macro (body: Code)`
\ No newline at end of file
// A powerful feature of Onyx that enables macros to be very useful is code blocks.
// Code blocks allow you to capture code and treat it as a compile-time object that can
- // be passed around. To create a code blocks, simply put '#code' in front of the block
+ // be passed around. To create a code blocks, simply put '#quote' in front of the block
// of code you want to capture. Notice that this uses '::' because this is a compile-time
// value.
- simple_code :: #code {
+ simple_code :: #quote {
println("This is a code block!");
}
- // You can then use the '#insert' directive to place the code wherever you need it.
+ // You can then use the '#unquote' directive to place the code wherever you need it.
// We can paste it 3 times for examples:
- #insert simple_code;
- #insert simple_code;
- #insert simple_code;
+ #unquote simple_code;
+ #unquote simple_code;
+ #unquote simple_code;
// Because simple_code is a compile-time value, it can be passed to procedures as so:
triple :: ($body: Code) {
println("Running 3 times!");
- #insert body;
- #insert body;
- #insert body;
+ #unquote body;
+ #unquote body;
+ #unquote body;
}
triple(simple_code);
// compile-time parameter (the '$').
triple_macro :: macro (body: Code) {
println("Running 3 times in a macro!");
- #insert body;
- #insert body;
- #insert body;
+ #unquote body;
+ #unquote body;
+ #unquote body;
}
triple_macro(simple_code);
cool_block :: macro (param: i32, body: Code) {
local_variable := param * 2;
- #insert body;
+ #unquote body;
}
cool_block(10) {
--- /dev/null
+#load "core/std"
+#load "modules/http/module"
+#load "modules/json/module"
+
+use package core
+http :: package http
+
+main :: (args) => {
+ conn, err := http.connect("http://api.weatherapi.com");
+ if err != .None {
+ println(err);
+ os.exit(1);
+ }
+ defer conn->close();
+
+ w1 := alloc.heap.get_watermark();
+ f1 := alloc.heap.get_freed_size();
+
+ alloc.heap.auto() {
+ res := conn->get("/v1/current.json", .[
+ .{ "key", "59c2510355ba48d299b173546222103" },
+ .{ "q", http.urlencode("Sioux Falls, SD") },
+ ]);
+
+ j_data := res->json();
+
+ curr := j_data.root["current"];
+ printf("It is {.1} degrees outside in {}, but it feels like {.1}.\n",
+ curr["temp_f"]->as_float(),
+ j_data.root["location"]["name"]->as_str(),
+ curr["feelslike_f"]->as_float());
+ }
+
+ w2 := alloc.heap.get_watermark();
+ f2 := alloc.heap.get_freed_size();
+
+ printf("Leaked: {}\n", (w2 - f2) - (w1 - f1));
+}
switchnode->flags |= Ast_Flag_Has_Been_Checked;
// Should the case block code be checked here?
- // Or should this just exist to resolve macros and expand #inserts
+ // Or should this just exist to resolve macros and expand #unquotes
// then the cases are consumed into the array or cases, THEN the blocks
// are actually checked?
if (switchnode->cases == NULL) {
Type* code_type = type_build_from_ast(context.ast_alloc, builtin_code_type);
TYPE_CHECK(&insert->code_expr, code_type) {
- ERROR_(insert->token->pos, "#insert expected a value of type 'Code', got '%s'.",
+ ERROR_(insert->token->pos, "#unquote expected a value of type 'Code', got '%s'.",
type_get_name(insert->code_expr->type));
}
retval = (AstTyped *) defined;
break;
}
- else if (parse_possible_directive(parser, "code")) {
+ else if (parse_possible_directive(parser, "quote")) {
OnyxToken* code_token = parser->curr - 1;
AstCodeBlock* code_block = make_node(AstCodeBlock, Ast_Kind_Code_Block);
retval = (AstTyped *) code_block;
break;
}
- else if (parse_possible_directive(parser, "insert")) {
+ else if (parse_possible_directive(parser, "unquote")) {
AstDirectiveInsert* insert = make_node(AstDirectiveInsert, Ast_Kind_Directive_Insert);
insert->token = parser->curr - 1;
insert->code_expr = parse_expression(parser, 0);
parse_arguments(parser, ')', &call_node->args);
-// This could be a cool feature where you can write:
-//
-// foo(x, y) #{
-// // ...
-// }
-//
-// which just desugars into
-//
-// foo(x, y, #code {
-// // ...
-// })
-
// Wrap expressions in AstArgument
bh_arr_each(AstTyped *, arg, call_node->args.values) {
if ((*arg) == NULL) continue;
}
for ^cell: cells_to_consider {
- map.update(^grid, *cell, #code { it.alive = it.next; });
+ map.update(^grid, *cell, #quote { it.alive = it.next; });
}
array.clear(^cells_to_consider);
if (it & (1 << index)) != 0 do A += 1;
}
- expected := (1 << index) if (#insert comparison) else 0;
+ expected := (1 << index) if (#unquote comparison) else 0;
while i := 0; i < arr.count {
defer i += 1;
}
attempt_add :: macro (cond: Code, dx, dy: i32) {
- if #insert cond {
+ if #unquote cond {
if !tried->has(.{try.x + dx, try.y + dy}) {
if found := array.find_ptr(to_try.data, .{try.x + dx, try.y + dy, 0}); found != null {
found.cost = math.min(cell_value, found.cost);
printf("ba[10] is {}.\n", ba[10]);
sum := 0;
- bucket_array.for_each(ba, #code {
+ bucket_array.for_each(ba, #quote {
printf("[{}] -> {}\n", bucket_index, *it);
sum += *it;
});
Vector2 :: struct { x, y: i32; }
#operator == macro (v1: Vector2, v2: Vector2) => v1.x == v2.x && v1.y == v2.y;
-none_of_the_above :: #code {
+none_of_the_above :: #quote {
case #default {
println("Got default!");
}
switch it {
case "Thing" do println("Got thing!");
case "Some" do println("Got some!");
- #insert none_of_the_above;
+ #unquote none_of_the_above;
}
}
case .{ 1, 0 } do println("1, 0");
case .{ 1, 1 } do println("1, 1");
- #insert none_of_the_above;
+ #unquote none_of_the_above;
}
}
\ No newline at end of file