feat: add map2, map3, andThen to Astrid.Query

This commit is contained in:
YetAnotherMinion 2022-01-07 20:00:05 +00:00 committed by nobody
commit b6182376b6
Signed by: GrocerPublishAgent
GPG key ID: D460CD54A9E3AB86
12 changed files with 1202 additions and 1018 deletions

View 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": {}
}
}

Binary file not shown.

View 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)

View 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)

View file

@ -1,6 +1,7 @@
module Astrid.Query module Astrid.Query
exposing exposing
( Query ( Query
, andThen
, errorToString , errorToString
, execute , execute
, fetch , 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 : (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 = map5 f a b c d e =
Dummy Dummy
andThen : (a -> Query b) -> Query a -> Query b
andThen f a =
Dummy

View file

@ -68,7 +68,11 @@ pub fn load_interfaces(
elmi::DependencyInterface::Public(interface) => { elmi::DependencyInterface::Public(interface) => {
interfaces.insert(module_name, 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); //println!("skipping private interface {}", package_name);
//for (k, v) in unions { //for (k, v) in unions {
// println!(" {}", k); // println!(" {}", k);

1037
src/exec/mod.rs Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
use crate::{InputType, OutputType}; use crate::exec::{InputType, OutputType};
use std::fmt::Display; use std::fmt::Display;
pub(crate) fn generate<S: AsRef<str>>( pub(crate) fn generate<S: AsRef<str>>(

View file

@ -205,6 +205,8 @@ var _Query_execute = function(query)
while (true) { while (true) {
var q; var q;
while(q = queries.pop()) { while(q = queries.pop()) {
__Debug_print("query =");
__Debug_print(q);
switch (q.$) { switch (q.$) {
case 0: case 0:
values.push(q.a); values.push(q.a);
@ -222,6 +224,8 @@ var _Query_execute = function(query)
break; break;
case 4: case 4:
__Debug_print("got a map");
__Debug_print(q)
callbacks.push({ $:'Map', a: q.f }) callbacks.push({ $:'Map', a: q.f })
// We know that the list of queries is limited to length 8, // We know that the list of queries is limited to length 8,
// which is much less then browser's stack overflow limits that // 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("processing callbacks stack");
__Debug_print(callbacks);
__Debug_print("=====");
reduce: reduce:
while(callbacks.length > 0) { while(callbacks.length > 0) {
var last = callbacks[callbacks.length - 1]; var last = callbacks[callbacks.length - 1];
switch (last.$) { switch (last.$) {
case 'Map': case 'Map':
__Debug_print(last);
__Debug_print(values);
var arity = last.a.a; var arity = last.a.a;
if (values.length < arity) { if (values.length < arity) {
// This implies that queries.length > 0 because we must // This implies that queries.length > 0 because we must
@ -281,10 +289,14 @@ var _Query_execute = function(query)
callbacks.pop(); callbacks.pop();
// Directly call the wrapped Elm function since we know all // Directly call the wrapped Elm function since we know all
// the arguments // the arguments
__Debug_print("ready to call function");
var fun = last.a.f; var fun = last.a.f;
__Debug_print(typeof fun);
var args = values.slice(-arity); var args = values.slice(-arity);
values.length = values.length - args.length; 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; break;
case 'AndThen': case 'AndThen':
@ -297,6 +309,8 @@ var _Query_execute = function(query)
} }
if (queries.length == 0 && callbacks.length == 0) { if (queries.length == 0 && callbacks.length == 0) {
__Debug_print("final result");
__Debug_print(values);
// values must have one element in it. // values must have one element in it.
return $elm$core$Result$Ok(values.pop()) return $elm$core$Result$Ok(values.pop())
} }

File diff suppressed because it is too large Load diff

View file

@ -123,7 +123,7 @@ impl From<rusty_v8::DataError> for InterpreterError {
impl TypeError { impl TypeError {
pub fn to_doc(&self) -> Doc { pub fn to_doc(&self) -> Doc {
let mut title = "TYPE ERROR"; let title = "TYPE ERROR";
use TypeError::*; use TypeError::*;
let message = match self { let message = match self {
CantEvalRecord => Doc::text("cant eval record"), CantEvalRecord => Doc::text("cant eval record"),

View file

@ -1,8 +1,8 @@
use crate::elm; use crate::elm;
use crate::reporting::{CompilerError, Problem, TypeError}; use crate::reporting::{CompilerError, Problem, TypeError};
use genco::lang::rust; use genco::lang::rust;
use genco::quote_in;
use genco::tokens::quoted; use genco::tokens::quoted;
use genco::{quote, quote_in};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::path::PathBuf; use std::path::PathBuf;
use tracing::info_span; 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); println!("found tail func {}", key);
} }
_ => { _ => {
@ -178,10 +178,10 @@ pub fn transpile(
} }
println!("total symbols {}", objects.len()); println!("total symbols {}", objects.len());
//let visited: HashSet<Global> = HashSet::new(); //let visited: HashSet<Global> = HashSet::new();
for (key, node) in objects.iter() { for (_key, node) in objects.iter() {
//println!("key {}", key); //println!("key {}", key);
match node { match node {
elmi::Node::Define(expr, deps) => { elmi::Node::Define(_expr, deps) => {
//println!("key => {:?}", expr); //println!("key => {:?}", expr);
for dep in deps.iter() { for dep in deps.iter() {
if !objects.contains_key(&dep) { 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 => quote_in! { *tokens =>
"i don't know how to code gen a function expression" "i don't know how to code gen a function expression"
//#(for elmi::Name(ref parameter) in parameters.iter() join (, ) => //#(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 { match &**fexpr {
elmi::Expr::VarGlobal(global @ elmi::Global(home, name)) => { elmi::Expr::VarGlobal(global @ elmi::Global(home, name)) => {
match symbol_table.get(&Symbol::Global(global)) { match symbol_table.get(&Symbol::Global(global)) {
Some(SymbolKind::Function { arity, tipe }) => { Some(SymbolKind::Function { arity, tipe: _ }) => {
if args.len() < *arity { if args.len() < *arity {
let mut closure_args = Vec::new(); let mut closure_args = Vec::new();
for i in 0..(*arity - args.len()) { 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); //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); panic!("tried to call a symbol we thought was a value: {}", global);
} }
None => { 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::TailCall(Name, Vec<(Name, Expr)>),
elmi::Expr::If(branches, final_branch) => { elmi::Expr::If(branches, _final_branch) => {
quote_in! { *tokens => quote_in! { *tokens =>
#(for (condition, expr) in branches join (#<push>#("} else")) => #(for (condition, expr) in branches join (#<push>#("} else")) =>
if #(ref out => codegen_expr(out, symbol_table, condition)) #("{") if #(ref out => codegen_expr(out, symbol_table, condition)) #("{")