Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions examples/program10.graphol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Composition examples: pass list to blocks and mutate nested lists.

show_list {
data inbox
echo ("received -> " data)
echo ("first item -> " (list_get data 0))
echo ("len -> " (list_len data))
}

payload (list "graph" "oriented" "language")
show_list payload run

mixed (list 1 "two" true (list 3 4))
echo ("mixed -> " mixed)
echo ("nested before push -> " (list_get mixed 3))

list_push (list_get mixed 3) 5
echo ("nested after push -> " (list_get mixed 3))
echo ("mixed after nested push -> " mixed)
18 changes: 18 additions & 0 deletions examples/program8.graphol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// List basics: create, push, get, set, pop, len.

nums (list 1 2 3)
echo ("initial -> " nums)

list_push nums 4
echo ("after push -> " nums)
echo ("len -> " (list_len nums))

echo ("index 0 -> " (list_get nums 0))
echo ("index 2 -> " (list_get nums 2))

list_set nums 1 99
echo ("after set index 1 -> " nums)

last (list_pop nums)
echo ("popped -> " last)
echo ("after pop -> " nums)
18 changes: 18 additions & 0 deletions examples/program9.graphol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Safe edge cases: empty pop, out-of-range get/set.

empty (list)
echo ("empty len -> " (list_len empty))

if (list_pop empty) {
echo "unexpected"
} else {
echo "pop on empty returns null (falsy)"
}

nums (list 10 20)
echo ("before invalid operations -> " nums)

echo ("out-of-range get (index 9) -> " (list_get nums 9))
list_set nums 9 777

echo ("after invalid set (should be unchanged) -> " nums)
9 changes: 8 additions & 1 deletion src/compiler/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const IO_SOURCE: &str = include_str!("../runtime/io.rs");
const VALUE_SOURCE: &str = include_str!("../runtime/value.rs");
const OBJECT_SOURCE: &str = include_str!("../runtime/object.rs");
const OBJECT_COMMANDS_SOURCE: &str = include_str!("../runtime/object/object_commands.rs");
const LIST_OBJECT_SOURCE: &str = include_str!("../runtime/object/list_object.rs");
const LIST_COMMANDS_SOURCE: &str = include_str!("../runtime/object/list_commands.rs");
const NODE_PRIMITIVES_SOURCE: &str =
include_str!("../runtime/object/object_strategies/node_primitives.rs");
const NUMERIC_OPS_SOURCE: &str = include_str!("../runtime/object/object_strategies/numeric_ops.rs");
Expand Down Expand Up @@ -60,6 +62,8 @@ fn runtime_module_source() -> String {

out.push_str(" pub mod object {\n");
push_nested_module(&mut out, "object_commands", OBJECT_COMMANDS_SOURCE, 2);
push_nested_module(&mut out, "list_object", LIST_OBJECT_SOURCE, 2);
push_nested_module(&mut out, "list_commands", LIST_COMMANDS_SOURCE, 2);

out.push_str(" mod object_strategies {\n");
out.push_str(" mod strategy_core {\n");
Expand Down Expand Up @@ -120,7 +124,10 @@ fn strip_object_module_decls(source: &str) -> String {
.lines()
.filter(|line| {
let trimmed = line.trim();
trimmed != "mod object_commands;" && trimmed != "mod object_strategies;"
trimmed != "mod object_commands;"
&& trimmed != "mod list_object;"
&& trimmed != "mod list_commands;"
&& trimmed != "mod object_strategies;"
})
.collect::<Vec<_>>()
.join("\n")
Expand Down
12 changes: 10 additions & 2 deletions src/runtime/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use super::host::ExecutionHost;
use super::io::{OutputEvent, OutputMode, RuntimeIo};
use super::object::{
BlockSnapshot, StdoutState, end_object, new_block, new_boolean_operator, new_logic_operator,
new_node, new_operator, receive_object,
new_list, new_node, new_operator, receive_object,
};
use super::scope::{Scope, ScopeRef};
use super::value::{ObjectRef, Value};
Expand Down Expand Up @@ -265,6 +265,10 @@ impl RuntimeEngine {
fn eval_root(&mut self, node: &NodeExpr, scope: &ScopeRef) -> Result<ObjectRef, RuntimeError> {
match node {
NodeExpr::Identifier(name) => {
if name == "list" {
return Ok(new_list());
}

if let Some(literal) = parse_literal(name) {
let node_ref = new_node();
receive_object(&node_ref, literal, self);
Expand Down Expand Up @@ -292,7 +296,11 @@ impl RuntimeEngine {
fn eval_message(&mut self, node: &NodeExpr, scope: &ScopeRef) -> Result<Value, RuntimeError> {
let value = match node {
NodeExpr::Identifier(name) => {
parse_literal(name).unwrap_or_else(|| Value::Obj(Scope::get(scope, name)))
if name == "list" {
Value::Obj(new_list())
} else {
parse_literal(name).unwrap_or_else(|| Value::Obj(Scope::get(scope, name)))
}
}
NodeExpr::StringLiteral(text) => Value::Text(text.clone()),
NodeExpr::Reserved(token) => Value::Obj(reserved_to_object(*token)?),
Expand Down
24 changes: 24 additions & 0 deletions src/runtime/object.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
mod object_commands;
mod list_commands;
mod list_object;
mod object_strategies;

use std::any::Any;
Expand All @@ -16,6 +18,8 @@ pub use object_commands::{
new_block, new_echo, new_if, new_input, new_message_async, new_message_else, new_message_run,
new_stdout, new_while,
};
pub use list_commands::{new_list_get, new_list_len, new_list_pop, new_list_push, new_list_set};
pub use list_object::new_list;
pub use object_strategies::{
new_boolean_operator, new_logic_operator, new_node, new_number, new_operator, new_string,
};
Expand Down Expand Up @@ -71,6 +75,26 @@ pub trait GrapholObject {
None
}

fn list_len(&self) -> Option<usize> {
None
}

fn list_get(&self, _index: usize) -> Option<Value> {
None
}

fn list_set(&mut self, _index: usize, _value: Value) -> bool {
false
}

fn list_pop(&mut self) -> Option<Value> {
None
}

fn list_push(&mut self, _value: Value) -> bool {
false
}

fn as_any(&self) -> &dyn Any;
}

Expand Down
Loading
Loading