vilterp / datalog-ts Goto Github PK
View Code? Open in Web Editor NEWa datalog interpreter in typescript
Home Page: https://lingo-workbench.dev/
License: MIT License
a datalog interpreter in typescript
Home Page: https://lingo-workbench.dev/
License: MIT License
react-simple-code-editor seems to handle this fine, so I must be doing something wrong…
e.g.
foo{a: A} :-
bar{b: b{b: A}}.
Would show an error as A
being unbound in head.
Hi! I like the ideas in https://petevilter.me/post/datalog-typechecking/ a lot, have also been playing with a couple of projects around it.
One indexes Clojure codebases using a Datascript database https://github.com/jpmonettas/clindex
and then writing some exploratory features of an IDE on top of it here https://github.com/jpmonettas/clograms.
Graphviz was removed because it conflicted with react-flow
, which was added for the drag-n-drop graph editor.
If there are two definitions in scope, both are highlighted as the definition.
Need some logic to choose the closer one, but not sure how to specify this in datalog without a reduce
construct or something…
Hi. Let me tell you about some projects very similar to what you are doing.
Let's start with Makam ( https://github.com/astampoulis/makam ). This is prolog/datalog-based language for specifying syntax and semantics of programming languages, for playing around and arguing about programming languages semantics. Makam is implemented in Ocaml.
Makam is a very similar language to your Datalog dialect. For example, here is example from their manual:
typeof (plus A B) tint <- typeof A tint, typeof B tint.
Makam has a lot of advanced features: lambda expressions, ability to very succinct implicit context (i. e. scope) handling (but I personally consider this as a misfeature, I like explicit contexts), special features for list handling (i. e. for dealing with target language's lists), etc.
Makam is so powerful that you can write whole interpreter in it (see details in their blog).
Makam is able to parse target language using PEG ( http://astampoulis.github.io/blog/makam-tutorial-01/ ). Parsing is bidirectorial (!). Parsing is somehow implemented using JS (but I'm not sure exactly how Ocaml parts and JS parts are related).
(Now let me insert one self-advertisement note here: every time I see "bidirectorial parsing" somewhere, I'm very skeptical about it. Very often so-called bidirectorial parsing projects turn out to be not sound. But I wrote a CFG-based Haskell library, that allows you to write bidirectorial parser with actual guaranteed soundness, i. e. my library guarantees bidirectionality. Here is link: https://mail.haskell.org/pipermail/haskell-cafe/2021-July/134217.html . I can show you other my Haskell parsing libs.)
Makam code can be evaluated directly in browser. At link above you can simply click to "Evaluate code" button in the corner and see result of code evaluation. You can edit code, too.
Unfortunately, Makam is not designed for implementing IDE, it is for writing interpreters and arguing about language semantics. So this will be very cool to somehow combine your IDE with great Makam features and its ability to implement full-featured interpreter.
Also Makam is typed.
This article https://www.tweag.io/blog/2019-11-28-PCF-makam-spec/ can be seen as simple introduction to Makam.
Makam is instance of broad category of Lambda-Prolog. Here is list of various Lambda-Prolog-based projects: http://www.lix.polytechnique.fr/~dale/lProlog/ . Lambda-Prolog can be described as Datalog, but typed, and with lambda expressions.
In particular see this cool demo: https://trymlts.github.io/ . This is playground for toy language MLTS. Interpreter for MLTS is implemented in Lambda-Prolog. And Lambda-Prolog can be run in browser. So this is similar to your demo. In both cases we implement simple language (FP or MLTS) in prolog/datalog-like language (Datalog and Lambda-Prolog, which are very similar). But in your case we see IDE without runner, and they have runner with editor, but without full-featured IDE
Mixup in native implementation between scopeID and rule name
e.g.
foo{} :-
bar{???}.
bar{x: X} :-
xxx{}.
expected suggestion x
; got nothing
Can fix by either porting RenameSpan
to FP, or removing FP, but I don't want to remove FP until Lingo has multi-arg functions (see #156)
Lord knows how to do this in Monaco. lol
These errors shouldn't be there:
Not sure why this isn't finding them:
datalog-ts/languageWorkbench/languages/dl/dl.ts
Lines 68 to 71 in 4a79913
Via some kind of currying.
Blocked by not supporting a left-recursive grammar…
Last item for parity with hardcoded FP.
We should be seeing an error here, since bar
has no attribute y
:
foo{x: A} :-
bar{y: A}.
bar{z: B} :-
baz{boop: B}.
This seems not to be working… Defined here:
datalog-ts/languageWorkbench/languages/dl/dl.ts
Lines 499 to 513 in 245c9f5
Variables that aren't declared in the head aren't being highlighted as definitions or usages.
It's an interesting question: are they definitions or usages? They're kind of both.
All language workbench examples show errors in the "Abstract Syntax Tree" and "Scope Graph" sections, and shows several errors in the console.
See log lingo-workbench.dev-1654054342512.log, snippets:
tree.tsx:65 Error: not found: astInternal.node
keyBindingsTable.tsx:11 error while checking availability of action "Jump to Definition": Error: not found: scope.Defn
keyBindingsTable.tsx:11 error while checking availability of action "Jump to First Error": Error: not found: tc.Problem
monacoIntegration.ts:149 in token provider: Error: not found: hl.mapping
probably just
-some_record{id: 22}
Repro
Expected
Actual
Calling rule:
hl.Segment{type: T, id: I, span: S, highlight: H} :-
hl.segmentInt{type: T, id: I, span: S, highlight: H} |
hl.segmentString{type: T, id: I, span: S, highlight: H} |
hl.segmentBool{type: T, id: I, span: S, highlight: H} |
hl.keyword{type: T, id: I, span: S, highlight: H} |
hl.segmentIdent{type: T, id: I, span: S, highlight: H} |
hl.segmentSpecialVar{type: T, id: I, span: S, highlight: H} |
hl.segmentIdentDefnHL{type: T, id: I, span: S, highlight: H} |
hl.segmentIdentUsageHL{type: T, id: I, span: S, highlight: H} |
hl.segmentComment{type: T, id: I, span: S, highlight: H}.
Works:
hl.segmentIdentDefnHL{type: "defn", span: S, highlight: true} :-
ide.CurrentDefnOrDefnOfCurrentVar{span: S}.
Doesn't work:
inlining ide.CurrentDefnOrDefnOfCurrentVar
:
hl.segmentIdentDefnHL{type: "defn", span: span{from: F, to: T}, highlight: true} :-
scope.Defn{span: span{from: F, to: T}} &
ide.Cursor{idx: CIdx} &
F <= CIdx & CIdx <= T.
These should work the same. Something's going wrong with bindings in the simple interpreter.
See c95bd72
Had to rename I
to RuleID
because I
had a binding from somewhere else. This shouldn't happen
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.