Skip to content

Commit

Permalink
feat: Engine 0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Oliver Linnarsson committed Jun 8, 2024
1 parent 9098a99 commit 22551f6
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 0 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,23 @@ gleam run # Run the project
gleam test # Run the tests
gleam shell # Run an Erlang shell
```

## Example blocks

```handlebars
{{#if some.prop}}
{{name}}
{{/if}}
```

```handlebars
{{#each some.prop}}
{{name}}
{{/each}}
```

```handlebars
{{#unless some.prop}}
{{name}}
{{/unless}}
```
87 changes: 87 additions & 0 deletions src/engine.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import compiler
import gleam/dynamic
import gleam/list
import gleam/string

pub type RuntimeError {
UnableToResolveProperty(path: List(String))
UnknownBlock(kind: String)
}

pub fn run(
ast: List(compiler.AST),
get_property: fn(List(String)) -> String,
) -> Result(String, List(RuntimeError)) {
case
ast
|> list.fold(#("", []), fn(acc, it) {
case it {
compiler.Constant(value) -> #(string.append(acc.0, value), acc.1)
compiler.Property(path) -> #(
string.append(acc.0, get_property(path)),
acc.1,
)
compiler.Block(kind, [], _) -> #(
acc.0,
list.append(acc.1, [UnknownBlock(kind)]),
)
compiler.Block(kind, [path_string, ..], children) ->
case kind {
"if" ->
case
get_property(string.split(path_string, "."))
|> dynamic.from
|> dynamic.bool()
{
Ok(True) ->
case run(children, get_property) {
Ok(str) -> #(string.append(acc.0, str), acc.1)
Error(_) -> #(
acc.0,
list.append(acc.1, [
UnableToResolveProperty(string.split(path_string, ".")),
]),
)
}
Ok(False) -> acc
Error(_) -> #(
acc.0,
list.append(acc.1, [
UnableToResolveProperty(string.split(path_string, ".")),
]),
)
}
"unless" ->
case
get_property(string.split(path_string, "."))
|> dynamic.from
|> dynamic.bool()
{
Ok(False) ->
case run(children, get_property) {
Ok(str) -> #(string.append(acc.0, str), acc.1)
Error(_) -> #(
acc.0,
list.append(acc.1, [
UnableToResolveProperty(string.split(path_string, ".")),
]),
)
}
Ok(True) -> acc
Error(_) -> #(
acc.0,
list.append(acc.1, [
UnableToResolveProperty(string.split(path_string, ".")),
]),
)
}
"while" -> todo
_ -> #(acc.0, list.append(acc.1, [UnknownBlock(kind)]))
}
}
})
{
#(ok, []) -> Ok(ok)
#(_, err) -> Error(err)
}
}
9 changes: 9 additions & 0 deletions test/engine_test.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import compiler
import engine
import gleeunit/should

pub fn engine_should_return_correct_when_running_hello_world_test() {
engine.run([compiler.Constant("Hello World")], fn(_) { "" })
|> should.be_ok
|> should.equal("Hello World")
}
13 changes: 13 additions & 0 deletions test/handles_test.gleam
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
import compiler
import engine
import gleam/result
import gleeunit
import gleeunit/should
import parser

pub fn main() {
gleeunit.main()
}

pub fn handles_hello_world_test() {
use res <- result.map(parser.parse("Hello World"))
use tokens <- result.map(res)
use ast <- result.map(compiler.compile(tokens, []))
use str <- result.map(engine.run(ast, fn(_) { "" }))
should.equal(str, "Hello World")
}

0 comments on commit 22551f6

Please sign in to comment.