Skip to content

Commit 0db76f2

Browse files
authored
Transition graphs (#194)
* compiles with ast graph using defs2 * add the within field to AstNode::Op * implement Ord for Type * make an path iterator over Tag * ast graph has changed over * update type graph to use defs2
1 parent f9a3edf commit 0db76f2

File tree

13 files changed

+767
-264
lines changed

13 files changed

+767
-264
lines changed

ogma/src/common/err.rs

+31
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use crate::{
44
lang::{
5+
defs2::ImplsIn,
56
help::*,
67
syntax::ast::*,
78
types::{Type, TypeDef},
@@ -139,6 +140,12 @@ pub fn help_as_error(msg: &HelpMessage, in_ty: Option<&Type>) -> Error {
139140
}
140141
}
141142

143+
pub fn help_msg_ambiguous_import() -> Option<String> {
144+
"check your imports for ambiguity\nconsider using fully qualified path syntax"
145+
.to_string()
146+
.into()
147+
}
148+
142149
// ###### ERROR ################################################################
143150
/// Create a single trace item using the tag.
144151
pub fn trace<D: Into<Option<String>>>(tag: &Tag, desc: D) -> Vec<Trace> {
@@ -216,6 +223,30 @@ impl Error {
216223
}
217224
}
218225

226+
pub(crate) fn op_not_found2(op: &Tag, recursion_detected: bool, impls: ImplsIn) -> Self {
227+
let alts = impls.fuzzy_find(op.str()).collect::<Vec<_>>();
228+
229+
let hlp = if recursion_detected {
230+
"recursion is not supported.
231+
for alternatives, please see <https://daedalus.report/d/docs/ogma.book/11%20(no)%20recursion.md?pwd-raw=docs>".into()
232+
} else if alts.is_empty() {
233+
"view a list of definitions using `def --list`".into()
234+
} else {
235+
alts.into_iter().fold(
236+
format!("`{op}` is implemented for the following input types:"),
237+
|s, t| s + " " + t.name,
238+
)
239+
};
240+
241+
Error {
242+
cat: Category::UnknownCommand,
243+
desc: format!("operation `{op}` not defined"),
244+
traces: trace(op, None),
245+
help_msg: Some(hlp),
246+
hard: true,
247+
}
248+
}
249+
219250
pub(crate) fn impl_not_found(op: &Tag, in_ty: &Type) -> Self {
220251
Error {
221252
cat: Category::Semantics,

ogma/src/eng/annotate.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ fn fmt(s: &mut String, blk: &Block, node: petgraph::prelude::NodeIndex, v: bool)
5454
write!(s, " }}").unwrap();
5555
fmt_ty(s, out_ty)
5656
}
57-
Op { op: _, blk: _ } => fmt_op(s, blk, OpNode(node), v),
57+
Op {
58+
op: _,
59+
blk: _,
60+
within: _,
61+
} => fmt_op(s, blk, OpNode(node), v),
5862
Def { .. } | Intrinsic { .. } | Flag { .. } => unreachable!(),
5963
}
6064
}

ogma/src/eng/arg.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,11 @@ impl<'a> ArgBuilder<'a> {
215215
} = compiler;
216216

217217
match &ag[node.idx()] {
218-
Op { op: _, blk: _ } => unreachable!("an argument cannot be an Op variant"),
218+
Op {
219+
op: _,
220+
blk: _,
221+
within: _,
222+
} => unreachable!("an argument cannot be an Op variant"),
219223
Flag(_) => unreachable!("an argument cannot be a Flag variant"),
220224
Intrinsic { .. } => unreachable!("an argument cannot be a Intrinsic variant"),
221225
Def { .. } => unreachable!("an argument cannot be a Def variant"),

ogma/src/eng/comp/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ pub fn compile_with_seed_vars(
3636
anon_tys: &AnonTypes,
3737
seed_vars: var::SeedVars,
3838
) -> Result<FullCompilation> {
39-
let (ag, chgs) = astgraph::init(expr, defs)?; // flatten and expand expr/defs
40-
let tg = TypeGraph::build(&ag, defs.types());
39+
let defs2 = defs2::Definitions::new();
40+
let (ag, chgs) = astgraph::init(expr, &defs2)?; // flatten and expand expr/defs
41+
let tg = TypeGraph::build(&ag, defs2.types());
4142
let lg = LocalsGraph::build(&ag);
4243

4344
let mut compiler = Box::new(Compiler {

ogma/src/eng/graphs/astgraph.rs

+42-28
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::*;
2+
use defs2::{Definitions, Id as DefId, TypesIn};
23
use kserd::Number;
34
use petgraph::prelude::*;
45
use std::ops::Deref;
@@ -23,6 +24,9 @@ pub enum AstNode {
2324
Op {
2425
op: Tag,
2526
blk: Tag,
27+
28+
/// The invocation location of the op.
29+
within: DefId,
2630
},
2731
Intrinsic {
2832
op: Tag,
@@ -107,7 +111,7 @@ pub fn init(expr: ast::Expression, defs: &Definitions) -> Result<(AstGraph, Chgs
107111

108112
let expr_tag = expr.tag.clone();
109113

110-
graph.flatten_expr(expr, &mut chgs, defs)?;
114+
graph.flatten_expr(expr, &mut chgs, defs, defs2::ROOT.into())?;
111115

112116
let recursion_detector = &mut RecursionDetection::default();
113117

@@ -130,6 +134,7 @@ impl AstGraph {
130134
expr: ast::Expression,
131135
chgs: &mut Chgs,
132136
defs: &Definitions,
137+
within: DefId,
133138
) -> Result<NodeIndex> {
134139
use ast::*;
135140

@@ -143,6 +148,7 @@ impl AstGraph {
143148
} = expr;
144149

145150
let root = g.add_node(AstNode::Expr(tag));
151+
let tys = defs.types().within(within);
146152

147153
// rather than building a recursive function, we'll use a queue of expressions to process,
148154
// since expressions are the recursive element
@@ -157,7 +163,7 @@ impl AstGraph {
157163
q.push_back(Qi {
158164
root,
159165
blocks,
160-
out_ty: map_ty_tag(out_ty, defs)?,
166+
out_ty: map_ty_tag(out_ty, tys)?,
161167
});
162168

163169
// FIFO -- breadth-first
@@ -187,13 +193,17 @@ impl AstGraph {
187193
}
188194
};
189195

190-
let op = g.add_node(AstNode::Op { op, blk: blk_tag });
196+
let op = g.add_node(AstNode::Op {
197+
op,
198+
blk: blk_tag,
199+
within,
200+
});
191201
g.add_edge(root, op, Relation::Normal); // edge from the expression root to the op
192202

193-
if let Some(t) = map_ty_tag(in_ty, defs)? {
203+
if let Some(t) = map_ty_tag(in_ty, tys)? {
194204
chgs.push(Chg::ObligeInput(op, t));
195205
}
196-
if let Some(t) = map_ty_tag(out_ty, defs)? {
206+
if let Some(t) = map_ty_tag(out_ty, tys)? {
197207
chgs.push(Chg::ObligeOutput(op, t));
198208
}
199209

@@ -236,7 +246,7 @@ impl AstGraph {
236246
q.push_back(Qi {
237247
root: term,
238248
blocks,
239-
out_ty: map_ty_tag(out_ty, defs)?,
249+
out_ty: map_ty_tag(out_ty, tys)?,
240250
});
241251
}
242252
}
@@ -259,7 +269,7 @@ impl AstGraph {
259269
let ops = self
260270
.node_indices()
261271
// is an Op
262-
.filter_map(|n| self[n].op().map(|_| OpNode(n)))
272+
.filter_map(|n| self[n].op().map(|x| OpNode(n)))
263273
// have not already expanded it
264274
.filter(|&n| !self.op_expanded(n))
265275
.collect::<Vec<_>>();
@@ -283,20 +293,16 @@ impl AstGraph {
283293
) -> Result<bool> {
284294
let opnode_ = NodeIndex::from(opnode);
285295

286-
let op = self[opnode_]
287-
.op()
288-
.expect("opnode must be an Op variant")
289-
.0
290-
.clone();
296+
let (op, _, within) = self[opnode_].op().expect("opnode must be an Op variant");
297+
let op = op.clone();
291298

292-
let impls = defs.impls();
299+
let impls = defs.impls().within(within);
293300

294-
if !impls.contains_op(op.str()) {
295-
return Err(Error::op_not_found(&op, None, false, impls));
301+
let op_impls = impls.matches(&op)?;
302+
if op_impls.is_empty() {
303+
return Err(Error::op_not_found2(&op, false, impls));
296304
}
297305

298-
let op_impls = impls.iter_op(op.str());
299-
300306
recursion_detector.clear_cache();
301307

302308
let mut expanded = false;
@@ -331,7 +337,9 @@ impl AstGraph {
331337
}
332338

333339
// no recursion detected, this id will need to be added to the detector
334-
let tys = defs.types();
340+
// TODO: use something other than ROOT
341+
todo!();
342+
let tys = defs.types().within(defs2::ROOT);
335343
let params = def
336344
.params
337345
.iter()
@@ -342,7 +350,10 @@ impl AstGraph {
342350
expr: def.expr.tag.clone(),
343351
params,
344352
});
345-
let expr = self.flatten_expr(def.expr.clone(), chgs, defs)?;
353+
// TODO: use something other than ROOT
354+
// not sure what yet, need to consider how looking down into
355+
// ast works
356+
let expr = self.flatten_expr(def.expr.clone(), chgs, defs, todo!())?;
346357
// link cmd to expr
347358
self.0.add_edge(cmd, expr, Relation::Normal);
348359
// add the id into the recursion detector
@@ -402,9 +413,8 @@ impl AstGraph {
402413
}
403414
}
404415

405-
fn map_ty_tag(tag: Option<Tag>, defs: &Definitions) -> Result<Option<Type>> {
406-
tag.map(|t| defs.types().get_using_tag(&t).map(|x| x.clone()))
407-
.transpose()
416+
fn map_ty_tag(tag: Option<Tag>, tys: TypesIn) -> Result<Option<Type>> {
417+
tag.map(|t| tys.get(&t).map(Clone::clone)).transpose()
408418
}
409419

410420
#[derive(Default)]
@@ -709,9 +719,9 @@ impl AstGraph {
709719

710720
impl AstNode {
711721
/// If this is an op node, returns the `(op, blk)` tags.
712-
pub fn op(&self) -> Option<(&Tag, &Tag)> {
722+
pub fn op(&self) -> Option<(&Tag, &Tag, DefId)> {
713723
match self {
714-
AstNode::Op { op, blk } => Some((op, blk)),
724+
AstNode::Op { op, blk, within } => Some((op, blk, *within)),
715725
_ => None,
716726
}
717727
}
@@ -752,7 +762,11 @@ impl AstNode {
752762
use AstNode::*;
753763

754764
match self {
755-
Op { op, blk: _ } => op,
765+
Op {
766+
op,
767+
blk: _,
768+
within: _,
769+
} => op,
756770
Intrinsic { op, intrinsic: _ } => op,
757771
Def { expr, params: _ } => expr,
758772
Flag(f) => f,
@@ -770,7 +784,7 @@ impl fmt::Display for AstNode {
770784
use AstNode::*;
771785

772786
match self {
773-
Op { op, blk: _ } => write!(f, "Op({})", op.str()),
787+
Op { op, blk: _, within } => write!(f, "Op({})", op.str()),
774788
Intrinsic {
775789
op: _,
776790
intrinsic: _,
@@ -847,15 +861,15 @@ impl fmt::Display for Relation {
847861
}
848862

849863
impl Parameter {
850-
fn from_ast(param: &ast::Parameter, tys: &types::Types) -> Result<Self> {
864+
fn from_ast(param: &ast::Parameter, tys: TypesIn) -> Result<Self> {
851865
let ast::Parameter { ident, ty } = param;
852866

853867
let name = ident.clone();
854868
let ty = ty.as_ref();
855869
let ty = if ty.map(|t| t.str() == "Expr").unwrap_or(false) {
856870
ParameterTy::Expr
857871
} else {
858-
ty.map(|t| tys.get_using_tag(t))
872+
ty.map(|t| tys.get(t))
859873
.transpose()?
860874
.map(Clone::clone)
861875
.map(ParameterTy::Specified)

0 commit comments

Comments
 (0)