feat: add map2, map3, andThen to Astrid.Query
This commit is contained in:
parent
3cf23637d5
commit
b6182376b6
12 changed files with 1202 additions and 1018 deletions
26
examples/sqlite-integration/elm.json
Normal file
26
examples/sqlite-integration/elm.json
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"type": "application",
|
||||
"source-directories": [
|
||||
"src",
|
||||
"../../lib/sql/src"
|
||||
],
|
||||
"elm-version": "0.19.1",
|
||||
"dependencies": {
|
||||
"direct": {
|
||||
"elm/browser": "1.0.2",
|
||||
"elm/core": "1.0.5",
|
||||
"elm/html": "1.0.0",
|
||||
"elm/json": "1.1.3",
|
||||
"elm-community/array-extra": "2.4.0"
|
||||
},
|
||||
"indirect": {
|
||||
"elm/time": "1.0.0",
|
||||
"elm/url": "1.0.0",
|
||||
"elm/virtual-dom": "1.0.2"
|
||||
}
|
||||
},
|
||||
"test-dependencies": {
|
||||
"direct": {},
|
||||
"indirect": {}
|
||||
}
|
||||
}
|
||||
BIN
examples/sqlite-integration/example.sqlite
Normal file
BIN
examples/sqlite-integration/example.sqlite
Normal file
Binary file not shown.
47
examples/sqlite-integration/src/CombinatorsTest.elm
Normal file
47
examples/sqlite-integration/src/CombinatorsTest.elm
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
module CombinatorsTest exposing (main)
|
||||
|
||||
import Astrid.Query exposing (fetch, execute, errorToString, map3, fetchOne, andThen)
|
||||
import Json.Decode
|
||||
import Html exposing (Html, ul, li, text, code, node, div)
|
||||
import Array.Extra
|
||||
|
||||
main : Html msg
|
||||
main =
|
||||
let
|
||||
query =
|
||||
map3
|
||||
(\one two three ->
|
||||
one ++ " " ++ two ++ " " ++ three
|
||||
)
|
||||
(fetchOne "select json_quote('a')" [] Json.Decode.string)
|
||||
{-
|
||||
(andThen
|
||||
(\right ->
|
||||
map
|
||||
(\v ->
|
||||
"andThen( " ++ v ++ ""
|
||||
)
|
||||
(andThen
|
||||
(\left ->
|
||||
succeed "andThen"
|
||||
)
|
||||
)
|
||||
)
|
||||
(fetchOne "select json_quote('b')" [] Json.Decode.string)
|
||||
)
|
||||
-}
|
||||
(fetchOne "select json_quote('b')" [] Json.Decode.string)
|
||||
(fetchOne "select json_quote('c')" [] Json.Decode.string)
|
||||
in
|
||||
case execute query of
|
||||
Ok result ->
|
||||
div []
|
||||
[ node "style" []
|
||||
[ text "code { background-color: #f6f7f9; display: block; padding: 1em; border-radius: 4px; border 1px solid #eee; } "
|
||||
]
|
||||
, code []
|
||||
[ text result ]
|
||||
]
|
||||
|
||||
Err error ->
|
||||
Html.text (errorToString error)
|
||||
48
examples/sqlite-integration/src/ShowDatabaseSchema.elm
Normal file
48
examples/sqlite-integration/src/ShowDatabaseSchema.elm
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
module ShowDatabaseSchema exposing (main)
|
||||
|
||||
import Astrid.Query exposing (fetch, execute, errorToString)
|
||||
import Json.Decode
|
||||
import Html exposing (Html, ul, li, text, code, node, div)
|
||||
import Array.Extra
|
||||
|
||||
|
||||
main : Html msg
|
||||
main =
|
||||
let
|
||||
query =
|
||||
fetch
|
||||
"select json_object('type', type, 'name', name, 'sql', sql) from sqlite_master WHERE type = 'table'"
|
||||
[]
|
||||
(Json.Decode.map3
|
||||
(\kind name sql->
|
||||
(kind, name, sql)
|
||||
)
|
||||
(Json.Decode.field "type" Json.Decode.string)
|
||||
(Json.Decode.field "name" Json.Decode.string)
|
||||
(Json.Decode.field "sql" Json.Decode.string)
|
||||
)
|
||||
in
|
||||
case execute query of
|
||||
Ok results ->
|
||||
div []
|
||||
[ node "style" []
|
||||
[ text "code { background-color: #f6f7f9; display: block; padding: 1em; border-radius: 4px; border 1px solid #eee; } "
|
||||
]
|
||||
, ul []
|
||||
(Array.Extra.mapToList
|
||||
(\(kind, name, sql) ->
|
||||
li []
|
||||
[ text "type = "
|
||||
, text kind
|
||||
, text ", name ="
|
||||
, text name
|
||||
, code []
|
||||
[ text sql]
|
||||
]
|
||||
)
|
||||
results
|
||||
)
|
||||
]
|
||||
|
||||
Err error ->
|
||||
Html.text (errorToString error)
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
module Astrid.Query
|
||||
exposing
|
||||
( Query
|
||||
, andThen
|
||||
, errorToString
|
||||
, execute
|
||||
, fetch
|
||||
|
|
@ -93,3 +94,7 @@ map4 f a b c d =
|
|||
map5 : (a -> b -> c -> d -> e -> value) -> Query a -> Query b -> Query c -> Query d -> Query e -> Query value
|
||||
map5 f a b c d e =
|
||||
Dummy
|
||||
|
||||
andThen : (a -> Query b) -> Query a -> Query b
|
||||
andThen f a =
|
||||
Dummy
|
||||
|
|
|
|||
|
|
@ -68,7 +68,11 @@ pub fn load_interfaces(
|
|||
elmi::DependencyInterface::Public(interface) => {
|
||||
interfaces.insert(module_name, interface);
|
||||
}
|
||||
elmi::DependencyInterface::Private(package_name, unions, aliases) => {
|
||||
elmi::DependencyInterface::Private(
|
||||
_package_name,
|
||||
_unions,
|
||||
_aliases,
|
||||
) => {
|
||||
//println!("skipping private interface {}", package_name);
|
||||
//for (k, v) in unions {
|
||||
// println!(" {}", k);
|
||||
|
|
|
|||
1037
src/exec/mod.rs
Normal file
1037
src/exec/mod.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{InputType, OutputType};
|
||||
use crate::exec::{InputType, OutputType};
|
||||
use std::fmt::Display;
|
||||
|
||||
pub(crate) fn generate<S: AsRef<str>>(
|
||||
|
|
|
|||
|
|
@ -205,6 +205,8 @@ var _Query_execute = function(query)
|
|||
while (true) {
|
||||
var q;
|
||||
while(q = queries.pop()) {
|
||||
__Debug_print("query =");
|
||||
__Debug_print(q);
|
||||
switch (q.$) {
|
||||
case 0:
|
||||
values.push(q.a);
|
||||
|
|
@ -222,6 +224,8 @@ var _Query_execute = function(query)
|
|||
break;
|
||||
|
||||
case 4:
|
||||
__Debug_print("got a map");
|
||||
__Debug_print(q)
|
||||
callbacks.push({ $:'Map', a: q.f })
|
||||
// We know that the list of queries is limited to length 8,
|
||||
// which is much less then browser's stack overflow limits that
|
||||
|
|
@ -265,12 +269,16 @@ var _Query_execute = function(query)
|
|||
}
|
||||
|
||||
__Debug_print("processing callbacks stack");
|
||||
__Debug_print(callbacks);
|
||||
__Debug_print("=====");
|
||||
|
||||
reduce:
|
||||
while(callbacks.length > 0) {
|
||||
var last = callbacks[callbacks.length - 1];
|
||||
switch (last.$) {
|
||||
case 'Map':
|
||||
__Debug_print(last);
|
||||
__Debug_print(values);
|
||||
var arity = last.a.a;
|
||||
if (values.length < arity) {
|
||||
// This implies that queries.length > 0 because we must
|
||||
|
|
@ -281,10 +289,14 @@ var _Query_execute = function(query)
|
|||
callbacks.pop();
|
||||
// Directly call the wrapped Elm function since we know all
|
||||
// the arguments
|
||||
__Debug_print("ready to call function");
|
||||
var fun = last.a.f;
|
||||
__Debug_print(typeof fun);
|
||||
var args = values.slice(-arity);
|
||||
values.length = values.length - args.length;
|
||||
values.push(Function.prototype.apply(fun, args));
|
||||
args.reverse();
|
||||
__Debug_print({ args: args, values: values});
|
||||
values.push(fun.apply(null, args));
|
||||
break;
|
||||
|
||||
case 'AndThen':
|
||||
|
|
@ -297,6 +309,8 @@ var _Query_execute = function(query)
|
|||
}
|
||||
|
||||
if (queries.length == 0 && callbacks.length == 0) {
|
||||
__Debug_print("final result");
|
||||
__Debug_print(values);
|
||||
// values must have one element in it.
|
||||
return $elm$core$Result$Ok(values.pop())
|
||||
}
|
||||
|
|
|
|||
1015
src/main.rs
1015
src/main.rs
File diff suppressed because it is too large
Load diff
|
|
@ -123,7 +123,7 @@ impl From<rusty_v8::DataError> for InterpreterError {
|
|||
|
||||
impl TypeError {
|
||||
pub fn to_doc(&self) -> Doc {
|
||||
let mut title = "TYPE ERROR";
|
||||
let title = "TYPE ERROR";
|
||||
use TypeError::*;
|
||||
let message = match self {
|
||||
CantEvalRecord => Doc::text("cant eval record"),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use crate::elm;
|
||||
use crate::reporting::{CompilerError, Problem, TypeError};
|
||||
use genco::lang::rust;
|
||||
use genco::quote_in;
|
||||
use genco::tokens::quoted;
|
||||
use genco::{quote, quote_in};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::path::PathBuf;
|
||||
use tracing::info_span;
|
||||
|
|
@ -124,7 +124,7 @@ pub fn transpile(
|
|||
);
|
||||
}
|
||||
}
|
||||
elmi::Node::DefineTailFunc(arg_names, expr, _deps) => {
|
||||
elmi::Node::DefineTailFunc(_arg_names, _expr, _deps) => {
|
||||
println!("found tail func {}", key);
|
||||
}
|
||||
_ => {
|
||||
|
|
@ -178,10 +178,10 @@ pub fn transpile(
|
|||
}
|
||||
println!("total symbols {}", objects.len());
|
||||
//let visited: HashSet<Global> = HashSet::new();
|
||||
for (key, node) in objects.iter() {
|
||||
for (_key, node) in objects.iter() {
|
||||
//println!("key {}", key);
|
||||
match node {
|
||||
elmi::Node::Define(expr, deps) => {
|
||||
elmi::Node::Define(_expr, deps) => {
|
||||
//println!("key => {:?}", expr);
|
||||
for dep in deps.iter() {
|
||||
if !objects.contains_key(&dep) {
|
||||
|
|
@ -498,7 +498,7 @@ fn codegen_expr(tokens: &mut rust::Tokens, symbol_table: &mut SymbolTable, expr:
|
|||
}
|
||||
}
|
||||
}
|
||||
elmi::Expr::Function(parameters, body) => {
|
||||
elmi::Expr::Function(_parameters, _body) => {
|
||||
quote_in! { *tokens =>
|
||||
"i don't know how to code gen a function expression"
|
||||
//#(for elmi::Name(ref parameter) in parameters.iter() join (, ) =>
|
||||
|
|
@ -509,7 +509,7 @@ fn codegen_expr(tokens: &mut rust::Tokens, symbol_table: &mut SymbolTable, expr:
|
|||
match &**fexpr {
|
||||
elmi::Expr::VarGlobal(global @ elmi::Global(home, name)) => {
|
||||
match symbol_table.get(&Symbol::Global(global)) {
|
||||
Some(SymbolKind::Function { arity, tipe }) => {
|
||||
Some(SymbolKind::Function { arity, tipe: _ }) => {
|
||||
if args.len() < *arity {
|
||||
let mut closure_args = Vec::new();
|
||||
for i in 0..(*arity - args.len()) {
|
||||
|
|
@ -542,7 +542,7 @@ fn codegen_expr(tokens: &mut rust::Tokens, symbol_table: &mut SymbolTable, expr:
|
|||
}
|
||||
//println!("found the function symbol {}, arity {}", global, arity);
|
||||
}
|
||||
Some(SymbolKind::Value { tipe }) => {
|
||||
Some(SymbolKind::Value { tipe: _ }) => {
|
||||
panic!("tried to call a symbol we thought was a value: {}", global);
|
||||
}
|
||||
None => {
|
||||
|
|
@ -571,7 +571,7 @@ fn codegen_expr(tokens: &mut rust::Tokens, symbol_table: &mut SymbolTable, expr:
|
|||
};
|
||||
}
|
||||
//elmi::Expr::TailCall(Name, Vec<(Name, Expr)>),
|
||||
elmi::Expr::If(branches, final_branch) => {
|
||||
elmi::Expr::If(branches, _final_branch) => {
|
||||
quote_in! { *tokens =>
|
||||
#(for (condition, expr) in branches join (#<push>#("} else")) =>
|
||||
if #(ref out => codegen_expr(out, symbol_table, condition)) #("{")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue