Compare commits

..

No commits in common. "324fa948e66d0858a9660dfe95f61ddfc02bc9dc" and "dde7df4604eafe62834969557a6727d5992e1356" have entirely different histories.

13 changed files with 237 additions and 143 deletions

View File

@ -1,72 +0,0 @@
PrecApp @ prec(app(?l, ?r), 100, left) <-;
PrecPlus @ prec(plus(?l, ?r), 80, either) <-;
PrecAbs @ prec(abs(?x, ?t, ?e), 0, right) <-;
PrecArr @ prec(tarr(?l, ?r), 0, right) <-;
SelectHead @ select(cons([?t, ?v], ?rest), ?default, ?v) <- ?t;
SelectTail @ select(cons([?t, ?v], ?rest), ?default, ?found) <- not(?t), select(?rest, ?default, ?found);
SelectEmpty @ select(nil, ?default, ?default) <-;
ParenthAssocLeft @ parenthassoc(?a_i, left, right) <-;
ParenthAssocRight @ parenthassoc(?a_i, right, left) <-;
ParenthAssocNone @ parenthassoc(?a_i, none, ?pos) <-;
ParenthAssocNeq @ parenthassoc(?a_i, ?a_o, ?pos) <- not(symeq(?a_i, ?a_o));
Parenth @ parenth(?inner, ?outer, ?pos, ?strin, ?strout) <-
prec(?inner, ?p_i, ?a_i), prec(?outer, ?p_o, ?a_o),
join(["(", ?strin, ")"], ?strinparen),
select([ [less(?p_i, ?p_o), strinparen], [less(?p_o, ?p_i), ?strin], [ parenthassoc(?a_i, ?a_o, ?pos), ?strinparen ] ], ?strin, ?strout);
ParenthFallback @ parenth(?inner, ?outer, ?pos, ?strin, ?strin) <-;
LatexListNil @ latexlist(nil, nil) <-;
LatexListCons @ latexlist(cons(?x, ?xs), cons(?l_x, ?l_s)) <- latex(?x, ?l_x), latexlist(?xs, ?l_s);
IntercalateNil @ intercalate(?sep, nil, nil) <-;
IntercalateConsCons @ intercalate(?sep, cons(?x_1, cons(?x_2, ?xs)), cons(?x_1, cons(?sep, ?ys))) <- intercalate(?sep, cons(?x_2, ?xs), ?ys);
IntercalateConsNil @ intercalate(?sep, cons(?x, nil), cons(?x, nil)) <-;
NonEmpty @ nonempty(cons(?x, ?xs)) <-;
LatexInt @ latex(?i, ?l) <- int(?i), tostring(?i, ?l);
LatexFloat @ latex(?f, ?l) <- float(?f), tostring(?f, ?l);
LatexStr @ latex(?s, ?l) <- str(?s), escapestring(?s, ?l_1), latexifystring(?s, ?l_2), join(["\\texttt{\"", ?l_2, "\"}"], ?l);
LatexMeta @ latex(metavariable(?l), ?l) <-;
LatexLit @ latex(lit(?i), ?l) <- latex(?i, ?l);
LatexVar @ latex(var(?s), ?l) <- latex(?s, ?l);
LatexPlus @ latex(plus(?e_1, ?e_2), ?l) <-
latex(?e_1, ?l_1), latex(?e_2, ?l_2),
parenth(?e_1, plus(?e_1, ?e_2), left, ?l_1, ?lp_1),
parenth(?e_2, plus(?e_1, ?e_2), right, ?l_2, ?lp_2),
join([?lp_1, " + ", ?lp_2], ?l);
LatexPair @ latex(pair(?e_1, ?e_2), ?l) <- latex(?e_1, ?l_1), latex(?e_2, ?l_2), join(["(", ?l_1, ", ", ?l_2, ")"], ?l);
LatexAbs @ latex(abs(?x, ?t, ?e), ?l) <- latex(?e, ?l_e), latex(?t, ?l_t), latex(?x, ?l_x), join(["\\lambda ", ?l_x, " : ", ?l_t, " . ", ?l_e], ?l);
LatexApp @ latex(app(?e_1, ?e_2), ?l) <-
latex(?e_1, ?l_1), latex(?e_2, ?l_2),
parenth(?e_1, app(?e_1, ?e_2), left, ?l_1, ?lp_1),
parenth(?e_2, app(?e_1, ?e_2), right, ?l_2, ?lp_2),
join([?lp_1, " \\enspace ", ?lp_2], ?l);
LatexTInt @ latex(tint, "\\text{tint}") <-;
LatexTStr @ latex(tstr, "\\text{tstr}") <-;
LatexTArr @ latex(tarr(?t_1, ?t_2), ?l) <-
latex(?t_1, ?l_1), latex(?t_2, ?l_2),
parenth(?t_1, tarr(?t_1, ?t_2), left, ?l_1, ?lp_1),
parenth(?t_2, tarr(?t_1, ?t_2), right, ?l_2, ?lp_2),
join([?lp_1, " \\to ", ?lp_2], ?l);
LatexTPair @ latex(tpair(?t_1, ?t_2), ?l) <- latex(?t_1, ?l_1), latex(?t_2, ?l_2), join(["(", ?l_1, ", ", ?l_2, ")"], ?l);
LatexTypeEmpty @ latex(empty, "\\varnothing") <-;
LatexTypeExtend @ latex(extend(?a, ?b, ?c), ?l) <- latex(?a, ?l_a), latex(?b, ?l_b), latex(?c, ?l_c), join([?l_a, " , ", ?l_b, " : ", ?l_c], ?l);
LatexTypeInenv @ latex(inenv(?x, ?t, ?G), ?l) <-latex(?x, ?l_x), latex(?t, ?l_t), latex(?G, ?l_G), join([?l_x, " : ", ?l_t, " \\in ", ?l_G], ?l);
LatexTypeBin @ latex(type(?e, ?t), ?l) <- latex(?e, ?l_e), latex(?t, ?l_t), join([?l_e, " : ", ?l_t], ?l);
LatexTypeTer @ latex(type(?G, ?e, ?t), ?l) <- latex(?G, ?l_G), latex(?e, ?l_e), latex(?t, ?l_t), join([?l_G, " \\vdash ", ?l_e, " : ", ?l_t], ?l);
LatexConverts @ latex(converts(?f, ?t), ?l) <- latex(?f, ?l_f), latex(?t, ?l_t), join([?l_f, " \\preceq ", ?l_t], ?l);
LatexIsInt @ latex(int(?e), ?l) <- latex(?e, ?l_e), join([?l_e, " \\in \\texttt{Int}"], ?l);
LatexIsFloat @ latex(float(?e), ?l) <- latex(?e, ?l_e), join([?l_e, " \\in \\texttt{Float}"], ?l);
LatexIsNum @ latex(num(?e), ?l) <- latex(?e, ?l_e), join([?l_e, " \\in \\texttt{Num}"], ?l);
LatexIsStr @ latex(str(?e), ?l) <- latex(?e, ?l_e), join([?l_e, " \\in \\texttt{Str}"], ?l);
LatexSym @ latex(?s, ?l) <- sym(?s), tostring(?s, ?l_1), join(["\\text{", ?l_1,"}"], ?l);
LatexCall @ latex(?c, ?l) <- call(?c, ?n, ?ts), nonempty(?ts), latexlist(?ts, ?lts_1), intercalate(", ", ?lts_1, ?lts_2), join(?lts_2, ?lts_3), join(["\\text{", ?n, "}", "(", ?lts_3, ")"], ?l);

View File

@ -4,16 +4,11 @@ date: 2022-06-26T18:36:01-07:00
tags: ["Type Systems", "Programming Languages"] tags: ["Type Systems", "Programming Languages"]
series: "Everything I Know About Types" series: "Everything I Know About Types"
draft: true draft: true
bergamot:
render_presets:
default: "bergamot/rendering/lc.bergamot"
presets:
intro:
prompt: "type(TERM, ?t)"
query: ""
file: "intro.bergamot"
--- ---
{{< katex_component_js >}}
{{< bergamot_js_css >}}
I am in love with types and type systems. They are, quite probably, I am in love with types and type systems. They are, quite probably,
my favorite concept in the world. Most of us mere my favorite concept in the world. Most of us mere
mortals use types as a way to make sure we aren't writing mortals use types as a way to make sure we aren't writing
@ -176,6 +171,12 @@ to the tool than to type theory itself; I will denote these exercises as such wh
possible. Also, whenever the context of the exercise can be loaded into possible. Also, whenever the context of the exercise can be loaded into
Bergamot, I will denote this with a play button. Bergamot, I will denote this with a play button.
{{< bergamot_exercise label="bergamot; sample exercise" preset="intro" id="exercise-2" >}} {{< bergamot_preset name="intro-preset" prompt="type(TERM, ?t)" >}}
TNumber @ type(lit(?n), number) <- num(?n);
TPlusI @ type(plus(?e_1, ?e_2), number) <-
type(?e_1, number), type(?e_2, number);
{{< /bergamot_preset >}}
{{< bergamot_exercise label="bergamot; sample exercise" preset="intro-preset" id="exercise-2" >}}
Try typing `1+1` into the input field! Try typing `1+1` into the input field!
{{< /bergamot_exercise >}} {{< /bergamot_exercise >}}

View File

@ -1,3 +0,0 @@
TNumber @ type(lit(?n), number) <- num(?n);
TPlusI @ type(plus(?e_1, ?e_2), number) <-
type(?e_1, number), type(?e_2, number);

View File

@ -4,25 +4,11 @@ date: 2022-06-30T19:08:50-07:00
tags: ["Type Systems", "Programming Languages"] tags: ["Type Systems", "Programming Languages"]
series: "Everything I Know About Types" series: "Everything I Know About Types"
draft: true draft: true
bergamot:
render_presets:
default: "bergamot/rendering/lc.bergamot"
presets:
notation:
prompt: "type(TERM, ?t)"
query: ""
file: "notation.bergamot"
string:
prompt: "type(TERM, ?t)"
query: "\"hello\"+\"world\""
file: "string.bergamot"
conversion:
prompt: "type(TERM, ?t)"
query: ""
file: "conversion.bergamot"
--- ---
{{< katex_component_js >}}
{{< bergamot_js_css >}}
It's finally time to start looking at types. As I mentioned, I want It's finally time to start looking at types. As I mentioned, I want
to take an approach that draws a variety of examples from the real to take an approach that draws a variety of examples from the real
world - I'd like to talk about examples from real programming world - I'd like to talk about examples from real programming
@ -128,7 +114,11 @@ Another consequence of this is that not everyone agrees on notation; according
to [this paper](https://labs.oracle.com/pls/apex/f?p=LABS:0::APPLICATION_PROCESS%3DGETDOC_INLINE:::DOC_ID:959), to [this paper](https://labs.oracle.com/pls/apex/f?p=LABS:0::APPLICATION_PROCESS%3DGETDOC_INLINE:::DOC_ID:959),
27 different ways of writing down substitutions were observed in the POPL conference alone. 27 different ways of writing down substitutions were observed in the POPL conference alone.
{{< bergamot_exercise label="bergamot; tweaking notation" preset="notation" id="exercise-1" >}} {{< bergamot_preset name="notation-preset" prompt="type(TERM, ?t)" >}}
TNumber @ type(lit(?n), number) <- num(?n);
{{< /bergamot_preset >}}
{{< bergamot_exercise label="bergamot; tweaking notation" preset="notation-preset" id="exercise-1" >}}
Bergamot, the interactive tool I've developed for doing exercises, supports Bergamot, the interactive tool I've developed for doing exercises, supports
customizing the notation for rules. Try changing the \(:\) symbol to customizing the notation for rules. Try changing the \(:\) symbol to
the \(\sim\) symbol (denoted in latex as `\sim`). the \(\sim\) symbol (denoted in latex as `\sim`).
@ -327,7 +317,13 @@ This rule is read as follows:
> If \(e_1\) and \(e_2\) have type \(\text{string}\), then \(e_1+e_2\) has type \(\text{string}\). > If \(e_1\) and \(e_2\) have type \(\text{string}\), then \(e_1+e_2\) has type \(\text{string}\).
{{< bergamot_exercise label="bergamot; adding rules for strings" preset="string" id="exercise-2" >}} {{< bergamot_preset name="string-preset" prompt="type(TERM, ?t)" query="\"hello\"+\"world\"">}}
TNumber @ type(lit(?n), number) <- num(?n);
TPlusI @ type(plus(?e_1, ?e_2), number) <-
type(?e_1, number), type(?e_2, number);
{{< /bergamot_preset >}}
{{< bergamot_exercise label="bergamot; adding rules for strings" preset="string-preset" id="exercise-2" >}}
Try writing the Bergamot rules that correspond to the inference rule for strings Try writing the Bergamot rules that correspond to the inference rule for strings
above. I've provided the rules for numbers; the rules for strings should be quite above. I've provided the rules for numbers; the rules for strings should be quite
similar. similar.
@ -388,7 +384,29 @@ from the conversion rules. Chapter 15 of _Types and Programming Languages_
by Benjamin Pierce is a nice explanation, but the [Wikipedia page](https://en.wikipedia.org/wiki/Subtyping) by Benjamin Pierce is a nice explanation, but the [Wikipedia page](https://en.wikipedia.org/wiki/Subtyping)
ain't bad, either. ain't bad, either.
{{< bergamot_exercise label="advanced; a taste of conversions" preset="conversion" id="exercise-3" >}} {{< bergamot_preset name="conversion-preset" prompt="type(TERM, ?t)" >}}
section "Conversion rules" {
ConvertsIS @ converts(integer, string) <-;
ConvertsIF @ converts(integer, float) <-;
ConvertsFS @ converts(float, string) <-;
}
section "Rules for literals" {
TInt @ type(lit(?n), integer) <- int(?n);
TFloat @ type(lit(?f), float) <- float(?f);
TString @ type(lit(?s), string) <- str(?s);
}
section "" {
TPlusInt @ type(plus(?e_1, ?e_2), integer) <- type(?e_1, integer), type(?e_2, integer);
TPlusFloat @ type(plus(?e_1, ?e_2), float) <- type(?e_1, float), type(?e_2, float);
TPlusString @ type(plus(?e_1, ?e_2), string) <- type(?e_1, string), type(?e_2, string);
}
TConverts @ type(?e, ?tau_2) <- type(?e, ?tau_1), converts(?tau_1, ?tau_2);
{{< /bergamot_preset >}}
{{< bergamot_exercise label="advanced; a taste of conversions" preset="conversion-preset" id="exercise-3" >}}
This exercise is simply an early taste of formalizing conversions, which This exercise is simply an early taste of formalizing conversions, which
allow users to (for example) write numbers where the language expects strings, with the allow users to (for example) write numbers where the language expects strings, with the
understanding that the number will be automatically turned into a string. understanding that the number will be automatically turned into a string.

View File

@ -1,19 +0,0 @@
section "Conversion rules" {
ConvertsIS @ converts(integer, string) <-;
ConvertsIF @ converts(integer, float) <-;
ConvertsFS @ converts(float, string) <-;
}
section "Rules for literals" {
TInt @ type(lit(?n), integer) <- int(?n);
TFloat @ type(lit(?f), float) <- float(?f);
TString @ type(lit(?s), string) <- str(?s);
}
section "" {
TPlusInt @ type(plus(?e_1, ?e_2), integer) <- type(?e_1, integer), type(?e_2, integer);
TPlusFloat @ type(plus(?e_1, ?e_2), float) <- type(?e_1, float), type(?e_2, float);
TPlusString @ type(plus(?e_1, ?e_2), string) <- type(?e_1, string), type(?e_2, string);
}
TConverts @ type(?e, ?tau_2) <- type(?e, ?tau_1), converts(?tau_1, ?tau_2);

View File

@ -1 +0,0 @@
TNumber @ type(lit(?n), number) <- num(?n);

View File

@ -1,3 +0,0 @@
TNumber @ type(lit(?n), number) <- num(?n);
TPlusI @ type(plus(?e_1, ?e_2), number) <-
type(?e_1, number), type(?e_2, number);

View File

@ -3,11 +3,11 @@ title: "Bergamot: Exploring Programming Language Inference Rules"
date: 2023-12-22T18:16:44-08:00 date: 2023-12-22T18:16:44-08:00
tags: ["Project", "Programming Languages"] tags: ["Project", "Programming Languages"]
description: "In this post, I show off Bergamot, a tiny logic programming language and an idea for teaching inference rules." description: "In this post, I show off Bergamot, a tiny logic programming language and an idea for teaching inference rules."
bergamot:
render_presets:
default: "bergamot/rendering/lc.bergamot"
--- ---
{{< katex_component_js >}}
{{< bergamot_js_css >}}
### Inference Rules and the Study of Programming Languages ### Inference Rules and the Study of Programming Languages
In this post, I will talk about _inference rules_, particularly in the field In this post, I will talk about _inference rules_, particularly in the field
of programming language theory. The first question to get out of the way is of programming language theory. The first question to get out of the way is

View File

@ -0,0 +1,179 @@
<script defer src="{{ .Site.Params.bergamotJsUrl }}"></script>
<script defer src="{{ .Site.Params.bergamotObjectLanguageJsUrl }}"></script>
{{ $style := resources.Get "scss/bergamot.scss" | resources.ToCSS | resources.Minify }}
<link rel="stylesheet" href="{{ $style.Permalink }}">
<script defer>
const renderRules =
`
PrecApp @ prec(app(?l, ?r), 100, left) <-;
PrecPlus @ prec(plus(?l, ?r), 80, either) <-;
PrecAbs @ prec(abs(?x, ?t, ?e), 0, right) <-;
PrecArr @ prec(tarr(?l, ?r), 0, right) <-;
SelectHead @ select(cons([?t, ?v], ?rest), ?default, ?v) <- ?t;
SelectTail @ select(cons([?t, ?v], ?rest), ?default, ?found) <- not(?t), select(?rest, ?default, ?found);
SelectEmpty @ select(nil, ?default, ?default) <-;
ParenthAssocLeft @ parenthassoc(?a_i, left, right) <-;
ParenthAssocRight @ parenthassoc(?a_i, right, left) <-;
ParenthAssocNone @ parenthassoc(?a_i, none, ?pos) <-;
ParenthAssocNeq @ parenthassoc(?a_i, ?a_o, ?pos) <- not(symeq(?a_i, ?a_o));
Parenth @ parenth(?inner, ?outer, ?pos, ?strin, ?strout) <-
prec(?inner, ?p_i, ?a_i), prec(?outer, ?p_o, ?a_o),
join(["(", ?strin, ")"], ?strinparen),
select([ [less(?p_i, ?p_o), strinparen], [less(?p_o, ?p_i), ?strin], [ parenthassoc(?a_i, ?a_o, ?pos), ?strinparen ] ], ?strin, ?strout);
ParenthFallback @ parenth(?inner, ?outer, ?pos, ?strin, ?strin) <-;
LatexListNil @ latexlist(nil, nil) <-;
LatexListCons @ latexlist(cons(?x, ?xs), cons(?l_x, ?l_s)) <- latex(?x, ?l_x), latexlist(?xs, ?l_s);
IntercalateNil @ intercalate(?sep, nil, nil) <-;
IntercalateConsCons @ intercalate(?sep, cons(?x_1, cons(?x_2, ?xs)), cons(?x_1, cons(?sep, ?ys))) <- intercalate(?sep, cons(?x_2, ?xs), ?ys);
IntercalateConsNil @ intercalate(?sep, cons(?x, nil), cons(?x, nil)) <-;
NonEmpty @ nonempty(cons(?x, ?xs)) <-;
LatexInt @ latex(?i, ?l) <- int(?i), tostring(?i, ?l);
LatexFloat @ latex(?f, ?l) <- float(?f), tostring(?f, ?l);
LatexStr @ latex(?s, ?l) <- str(?s), escapestring(?s, ?l_1), latexifystring(?s, ?l_2), join(["\\\\texttt{\\"", ?l_2, "\\"}"], ?l);
LatexMeta @ latex(metavariable(?l), ?l) <-;
LatexLit @ latex(lit(?i), ?l) <- latex(?i, ?l);
LatexVar @ latex(var(?s), ?l) <- latex(?s, ?l);
LatexPlus @ latex(plus(?e_1, ?e_2), ?l) <-
latex(?e_1, ?l_1), latex(?e_2, ?l_2),
parenth(?e_1, plus(?e_1, ?e_2), left, ?l_1, ?lp_1),
parenth(?e_2, plus(?e_1, ?e_2), right, ?l_2, ?lp_2),
join([?lp_1, " + ", ?lp_2], ?l);
LatexPair @ latex(pair(?e_1, ?e_2), ?l) <- latex(?e_1, ?l_1), latex(?e_2, ?l_2), join(["(", ?l_1, ", ", ?l_2, ")"], ?l);
LatexAbs @ latex(abs(?x, ?t, ?e), ?l) <- latex(?e, ?l_e), latex(?t, ?l_t), latex(?x, ?l_x), join(["\\\\lambda ", ?l_x, " : ", ?l_t, " . ", ?l_e], ?l);
LatexApp @ latex(app(?e_1, ?e_2), ?l) <-
latex(?e_1, ?l_1), latex(?e_2, ?l_2),
parenth(?e_1, app(?e_1, ?e_2), left, ?l_1, ?lp_1),
parenth(?e_2, app(?e_1, ?e_2), right, ?l_2, ?lp_2),
join([?lp_1, " \\\\enspace ", ?lp_2], ?l);
LatexTInt @ latex(tint, "\\\\text{tint}") <-;
LatexTStr @ latex(tstr, "\\\\text{tstr}") <-;
LatexTArr @ latex(tarr(?t_1, ?t_2), ?l) <-
latex(?t_1, ?l_1), latex(?t_2, ?l_2),
parenth(?t_1, tarr(?t_1, ?t_2), left, ?l_1, ?lp_1),
parenth(?t_2, tarr(?t_1, ?t_2), right, ?l_2, ?lp_2),
join([?lp_1, " \\\\to ", ?lp_2], ?l);
LatexTPair @ latex(tpair(?t_1, ?t_2), ?l) <- latex(?t_1, ?l_1), latex(?t_2, ?l_2), join(["(", ?l_1, ", ", ?l_2, ")"], ?l);
LatexTypeEmpty @ latex(empty, "\\\\varnothing") <-;
LatexTypeExtend @ latex(extend(?a, ?b, ?c), ?l) <- latex(?a, ?l_a), latex(?b, ?l_b), latex(?c, ?l_c), join([?l_a, " , ", ?l_b, " : ", ?l_c], ?l);
LatexTypeInenv @ latex(inenv(?x, ?t, ?G), ?l) <-latex(?x, ?l_x), latex(?t, ?l_t), latex(?G, ?l_G), join([?l_x, " : ", ?l_t, " \\\\in ", ?l_G], ?l);
LatexTypeBin @ latex(type(?e, ?t), ?l) <- latex(?e, ?l_e), latex(?t, ?l_t), join([?l_e, " : ", ?l_t], ?l);
LatexTypeTer @ latex(type(?G, ?e, ?t), ?l) <- latex(?G, ?l_G), latex(?e, ?l_e), latex(?t, ?l_t), join([?l_G, " \\\\vdash ", ?l_e, " : ", ?l_t], ?l);
LatexConverts @ latex(converts(?f, ?t), ?l) <- latex(?f, ?l_f), latex(?t, ?l_t), join([?l_f, " \\\\preceq ", ?l_t], ?l);
LatexIsInt @ latex(int(?e), ?l) <- latex(?e, ?l_e), join([?l_e, " \\\\in \\\\texttt{Int}"], ?l);
LatexIsFloat @ latex(float(?e), ?l) <- latex(?e, ?l_e), join([?l_e, " \\\\in \\\\texttt{Float}"], ?l);
LatexIsNum @ latex(num(?e), ?l) <- latex(?e, ?l_e), join([?l_e, " \\\\in \\\\texttt{Num}"], ?l);
LatexIsStr @ latex(str(?e), ?l) <- latex(?e, ?l_e), join([?l_e, " \\\\in \\\\texttt{Str}"], ?l);
LatexSym @ latex(?s, ?l) <- sym(?s), tostring(?s, ?l_1), join(["\\\\text{", ?l_1,"}"], ?l);
LatexCall @ latex(?c, ?l) <- call(?c, ?n, ?ts), nonempty(?ts), latexlist(?ts, ?lts_1), intercalate(", ", ?lts_1, ?lts_2), join(?lts_2, ?lts_3), join(["\\\\text{", ?n, "}", "(", ?lts_3, ")"], ?l);
`;
const loadedWidgets = {};
const getButtons = (inputGroup) => {
return {
play: inputGroup.querySelector(".bergamot-play"),
reset: inputGroup.querySelector(".bergamot-reset"),
close: inputGroup.querySelector(".bergamot-close"),
}
}
const setRunning = (inputGroup, running) => {
if (inputGroup !== null) {
const buttons = getButtons(inputGroup);
if (buttons.play) buttons.play.classList.toggle("bergamot-hidden", running);
if (buttons.reset) buttons.reset.classList.toggle("bergamot-hidden", !running);
if (buttons.close) buttons.close.classList.toggle("bergamot-hidden", !running);
}
}
// The object language parsing is handling by a separate standalone Elm
// application in the ObjectLanguage module, which has two ports:
//
// * `parseString` requests a string to be parsed
// * `parsedString` returns the parsed string, or null
//
// We want there to be a single global ObjectLanguage object, but it works
// on a "subscription" model (we have to give a callback to its port).
// Configure this callback to invoke `resolve` functions from a list,
// so that callers can just get a promise. This way we aren't continuously
// registering more and more handlers for each parsed string, and we can
// use a convenient promise API.
const parsingPromiseResolvers = {};
const ensureObjectLanguage = () => {
if (!window.Bergamot.ObjectLanguage) {
window.Bergamot.ObjectLanguage = Elm.Bergamot.ObjectLanguage.init({});
window.Bergamot.ObjectLanguage.ports.parsedString.subscribe(({ string, term }) => {
if (string in parsingPromiseResolvers) {
for (const resolver of parsingPromiseResolvers[string]) {
resolver(term);
}
parsingPromiseResolvers[string] = [];
}
});
}
return window.Bergamot.ObjectLanguage;
}
const parseString = (str) => {
if (!(str in parsingPromiseResolvers)) {
parsingPromiseResolvers[str] = [];
}
return new Promise(resolve => {
parsingPromiseResolvers[str].push(resolve);
ensureObjectLanguage().ports.parseString.send(str);
});
}
window.Bergamot = {};
window.Bergamot.run = (inputGroup, nodeId, inputPrompt, rules, renderRules, input) => {
var app = Elm.Main.init({
node: document.getElementById(nodeId),
flags: {
inputModes: {
"Languge Term": { "custom": "Language Term" },
"Query": "query"
},
renderRules, rules, input
}
});
app.ports.convertInput.subscribe(async ({ mode, input }) => {
let query = await parseString(input);
if (query !== null) {
query = inputPrompt.replace("TERM", query);
app.ports.receiveConverted.send({ input, result: { query } });
} else {
app.ports.receiveConverted.send({ input, result: { error: "Unable to parse object language term" } });
}
});
loadedWidgets[nodeId] = { app, parentNode: inputGroup ? inputGroup.parentElement : null };
setRunning(inputGroup, true);
};
window.Bergamot.runPreset = (inputGroup, nodeId, presetName) => {
const preset = window.Bergamot.presets[presetName];
window.Bergamot.run(inputGroup, nodeId, preset.inputPrompt, preset.rules, renderRules, preset.query || "");
};
window.Bergamot.close = (inputGroup, nodeId) => {
if (!(nodeId in loadedWidgets)) return;
const placeholderDiv = document.createElement('div');
placeholderDiv.id = nodeId;
const widget = loadedWidgets[nodeId];
const elmRoot = widget.parentNode.querySelector(".bergamot-root");
elmRoot.replaceWith(placeholderDiv)
delete loadedWidgets[nodeId];
setRunning(inputGroup, false);
}
window.Bergamot.presets = {};
</script>

View File

@ -1,10 +1,7 @@
<script> <script>
window.addEventListener('load', function() {
window.Bergamot.presets['{{ .Get "name" }}'] = { window.Bergamot.presets['{{ .Get "name" }}'] = {
rules: '{{ .Inner }}', rules: '{{ .Inner }}',
inputPrompt: '{{ .Get "prompt" }}', inputPrompt: '{{ .Get "prompt" }}',
query: '{{ .Get "query" }}', query: '{{ .Get "query" }}',
renderPreset: '{{ default "default" (.Get "rendering") }}'
}; };
});
</script> </script>

View File

@ -1,3 +0,0 @@
<script>
window.Bergamot.renderPresets['{{ .Get "name" }}'] = '{{ .Inner }}';
</script>

View File

@ -1,6 +1,6 @@
<div id="{{ .Get "id" }}"></div> <div id="{{ .Get "id" }}"></div>
<script> <script>
window.addEventListener('load', function() { window.addEventListener('load', function() {
window.Bergamot.run(null, '{{ .Get "id" }}', '{{ .Get "prompt" }}', '{{ .Inner }}', '{{ default "default" (.Get "rendering") }}', '{{ .Get "query" }}'); window.Bergamot.run(null, '{{ .Get "id" }}', '{{ .Get "prompt" }}', '{{ .Inner }}', renderRules, '{{ .Get "query" }}');
}); });
</script> </script>

@ -1 +1 @@
Subproject commit 3a281dfa8aff1ac87d33d8f5ffcfc0a931a9656a Subproject commit acaa00754bb096e2bf3cc2c6caf415a3b2aa755e