more improvements
This commit is contained in:
parent
d877b42a12
commit
ec2944cdb7
5 changed files with 63 additions and 214 deletions
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
|
|
@ -16,7 +16,7 @@ importers:
|
||||||
version: 5.2.5
|
version: 5.2.5
|
||||||
dope2:
|
dope2:
|
||||||
specifier: git+https://deemz.org/git/joeri/dope2.git
|
specifier: git+https://deemz.org/git/joeri/dope2.git
|
||||||
version: git+https://deemz.org/git/joeri/dope2.git#1fe40858444cc4d0f9e4ba4223b280aef0ea4fb2
|
version: git+https://deemz.org/git/joeri/dope2.git#70fb80a9fc8438a588d1fba957706a322d0900d0
|
||||||
react:
|
react:
|
||||||
specifier: ^19.1.0
|
specifier: ^19.1.0
|
||||||
version: 19.1.0
|
version: 19.1.0
|
||||||
|
|
@ -597,8 +597,8 @@ packages:
|
||||||
deep-is@0.1.4:
|
deep-is@0.1.4:
|
||||||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
||||||
|
|
||||||
dope2@git+https://deemz.org/git/joeri/dope2.git#1fe40858444cc4d0f9e4ba4223b280aef0ea4fb2:
|
dope2@git+https://deemz.org/git/joeri/dope2.git#70fb80a9fc8438a588d1fba957706a322d0900d0:
|
||||||
resolution: {commit: 1fe40858444cc4d0f9e4ba4223b280aef0ea4fb2, repo: https://deemz.org/git/joeri/dope2.git, type: git}
|
resolution: {commit: 70fb80a9fc8438a588d1fba957706a322d0900d0, repo: https://deemz.org/git/joeri/dope2.git, type: git}
|
||||||
version: 0.0.1
|
version: 0.0.1
|
||||||
|
|
||||||
esbuild@0.25.4:
|
esbuild@0.25.4:
|
||||||
|
|
@ -1431,7 +1431,7 @@ snapshots:
|
||||||
|
|
||||||
deep-is@0.1.4: {}
|
deep-is@0.1.4: {}
|
||||||
|
|
||||||
dope2@git+https://deemz.org/git/joeri/dope2.git#1fe40858444cc4d0f9e4ba4223b280aef0ea4fb2:
|
dope2@git+https://deemz.org/git/joeri/dope2.git#70fb80a9fc8438a588d1fba957706a322d0900d0:
|
||||||
dependencies:
|
dependencies:
|
||||||
functional-red-black-tree: 1.0.1
|
functional-red-black-tree: 1.0.1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ const computeSuggestions = (text, env, suggestionPriority: (s: ResolvedType) =>
|
||||||
kind: type.kind || "value",
|
kind: type.kind || "value",
|
||||||
}]),
|
}]),
|
||||||
]
|
]
|
||||||
return []; // <-- uncomment to disable suggestions (useful for debugging)
|
// return []; // <-- uncomment to disable suggestions (useful for debugging)
|
||||||
return ls
|
return ls
|
||||||
.map(suggestion => [suggestionPriority(suggestion[2]), ...suggestion] as PrioritizedSuggestionType)
|
.map(suggestion => [suggestionPriority(suggestion[2]), ...suggestion] as PrioritizedSuggestionType)
|
||||||
.sort(([priorityA], [priorityB]) => priorityB - priorityA)
|
.sort(([priorityA], [priorityB]) => priorityB - priorityA)
|
||||||
|
|
@ -88,7 +88,12 @@ export function InputBlock({ state, setState, suggestionPriority, onCancel }: In
|
||||||
}
|
}
|
||||||
|
|
||||||
const onTextChange = newText => {
|
const onTextChange = newText => {
|
||||||
setState(state => ({...state, text: newText}));
|
setState(state => ({...state,
|
||||||
|
text: newText,
|
||||||
|
value: (trie.get(env.names)(newText) ? {
|
||||||
|
kind: "name",
|
||||||
|
} : state.value),
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// fired before onInput
|
// fired before onInput
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ export function Value({dynamic}) {
|
||||||
case symbolUUID:
|
case symbolUUID:
|
||||||
return <ValueUUID val={inst}/>
|
return <ValueUUID val={inst}/>
|
||||||
default:
|
default:
|
||||||
|
console.log("don't know how to show value:", dynamic);
|
||||||
return <>don't know how to show value</>;
|
return <>don't know how to show value</>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,184 +75,7 @@ export const tripleFunctionCallEditorState: ExprBlockState = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const biggerExample: ExprBlockState = {
|
export const biggerExample: ExprBlockState = {"kind":"let","inner":{"kind":"let","inner":{"kind":"let","inner":{"kind":"let","inner":{"kind":"input","text":"","value":{"kind":"text"},"focus":false},"name":"myListInc","value":{"kind":"call","fn":{"kind":"call","fn":{"kind":"input","text":"list.map","value":{"kind":"name"},"focus":false},"input":{"kind":"call","fn":{"kind":"call","fn":{"kind":"input","text":"list.map","value":{"kind":"name"},"focus":false},"input":{"kind":"input","text":"myList","value":{"kind":"name"},"focus":false}},"input":{"kind":"input","text":"inc","value":{"kind":"name"},"focus":false}}},"input":{"kind":"input","text":"id","value":{"kind":"name"},"focus":true}}},"name":"myList","value":{"kind":"call","fn":{"kind":"call","fn":{"kind":"input","text":"list.push","value":{"kind":"name"},"focus":false},"input":{"kind":"call","fn":{"kind":"call","fn":{"kind":"input","text":"list.push","value":{"kind":"name"},"focus":false},"input":{"kind":"call","fn":{"kind":"call","fn":{"kind":"input","text":"list.push","value":{"kind":"name"},"focus":false},"input":{"kind":"input","text":"list.emptyList","value":{"kind":"name"},"focus":false}},"input":{"kind":"input","text":"1","value":{"kind":"literal","type":"Int"},"focus":false}}},"input":{"kind":"input","text":"2","value":{"kind":"literal","type":"Int"},"focus":false}}},"input":{"kind":"input","text":"3","value":{"kind":"literal","type":"Int"},"focus":false}}},"name":"id","value":{"kind":"lambda","paramName":"x","expr":{"kind":"input","text":"x","value":{"kind":"name"},"focus":false}}},"name":"inc","value":{"kind":"lambda","paramName":"x","expr":{"kind":"call","fn":{"kind":"call","fn":{"kind":"input","text":"addInt","value":{"kind":"name"},"focus":false},"input":{"kind":"input","text":"x","value":{"kind":"name"},"focus":false}},"input":{"kind":"input","text":"1","value":{"kind":"literal","type":"Int"},"focus":true}}}};
|
||||||
"kind": "let",
|
|
||||||
"inner": {
|
|
||||||
"kind": "let",
|
|
||||||
"inner": {
|
|
||||||
"kind": "let",
|
|
||||||
"inner": {
|
|
||||||
"kind": "let",
|
|
||||||
"inner": {
|
|
||||||
"kind": "input",
|
|
||||||
"text": "",
|
|
||||||
"value": {
|
|
||||||
"kind": "text"
|
|
||||||
},
|
|
||||||
"focus": false
|
|
||||||
},
|
|
||||||
"name": "myListInc",
|
|
||||||
"value": {
|
|
||||||
"kind": "call",
|
|
||||||
"fn": {
|
|
||||||
"kind": "call",
|
|
||||||
"fn": {
|
|
||||||
"kind": "input",
|
|
||||||
"text": "list.map",
|
|
||||||
"value": {
|
|
||||||
"kind": "name"
|
|
||||||
},
|
|
||||||
"focus": false
|
|
||||||
},
|
|
||||||
"input": {
|
|
||||||
"kind": "input",
|
|
||||||
"text": "myList",
|
|
||||||
"value": {
|
|
||||||
"kind": "name"
|
|
||||||
},
|
|
||||||
"focus": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"input": {
|
|
||||||
"kind": "input",
|
|
||||||
"text": "inc",
|
|
||||||
"value": {
|
|
||||||
"kind": "name"
|
|
||||||
},
|
|
||||||
"focus": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"name": "myList",
|
|
||||||
"value": {
|
|
||||||
"kind": "call",
|
|
||||||
"fn": {
|
|
||||||
"kind": "call",
|
|
||||||
"fn": {
|
|
||||||
"kind": "input",
|
|
||||||
"text": "list.push",
|
|
||||||
"value": {
|
|
||||||
"kind": "name"
|
|
||||||
},
|
|
||||||
"focus": false
|
|
||||||
},
|
|
||||||
"input": {
|
|
||||||
"kind": "call",
|
|
||||||
"fn": {
|
|
||||||
"kind": "call",
|
|
||||||
"fn": {
|
|
||||||
"kind": "input",
|
|
||||||
"text": "list.push",
|
|
||||||
"value": {
|
|
||||||
"kind": "name"
|
|
||||||
},
|
|
||||||
"focus": false
|
|
||||||
},
|
|
||||||
"input": {
|
|
||||||
"kind": "call",
|
|
||||||
"fn": {
|
|
||||||
"kind": "call",
|
|
||||||
"fn": {
|
|
||||||
"kind": "input",
|
|
||||||
"text": "list.push",
|
|
||||||
"value": {
|
|
||||||
"kind": "name"
|
|
||||||
},
|
|
||||||
"focus": false
|
|
||||||
},
|
|
||||||
"input": {
|
|
||||||
"kind": "input",
|
|
||||||
"text": "list.emptyList",
|
|
||||||
"value": {
|
|
||||||
"kind": "name"
|
|
||||||
},
|
|
||||||
"focus": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"input": {
|
|
||||||
"kind": "input",
|
|
||||||
"text": "1",
|
|
||||||
"value": {
|
|
||||||
"kind": "literal",
|
|
||||||
"type": "Int"
|
|
||||||
},
|
|
||||||
"focus": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"input": {
|
|
||||||
"kind": "input",
|
|
||||||
"text": "2",
|
|
||||||
"value": {
|
|
||||||
"kind": "literal",
|
|
||||||
"type": "Int"
|
|
||||||
},
|
|
||||||
"focus": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"input": {
|
|
||||||
"kind": "input",
|
|
||||||
"text": "3",
|
|
||||||
"value": {
|
|
||||||
"kind": "literal",
|
|
||||||
"type": "Int"
|
|
||||||
},
|
|
||||||
"focus": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"name": "id",
|
|
||||||
"value": {
|
|
||||||
"kind": "lambda",
|
|
||||||
"paramName": "x",
|
|
||||||
"expr": {
|
|
||||||
"kind": "input",
|
|
||||||
"text": "x",
|
|
||||||
"value": {
|
|
||||||
"kind": "name"
|
|
||||||
},
|
|
||||||
"focus": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"name": "inc",
|
|
||||||
"value": {
|
|
||||||
"kind": "lambda",
|
|
||||||
"paramName": "x",
|
|
||||||
"expr": {
|
|
||||||
"kind": "call",
|
|
||||||
"fn": {
|
|
||||||
"kind": "call",
|
|
||||||
"fn": {
|
|
||||||
"kind": "input",
|
|
||||||
"text": "addInt",
|
|
||||||
"value": {
|
|
||||||
"kind": "name"
|
|
||||||
},
|
|
||||||
"focus": false
|
|
||||||
},
|
|
||||||
"input": {
|
|
||||||
"kind": "input",
|
|
||||||
"text": "x",
|
|
||||||
"value": {
|
|
||||||
"kind": "name"
|
|
||||||
},
|
|
||||||
"focus": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"input": {
|
|
||||||
"kind": "input",
|
|
||||||
"text": "1",
|
|
||||||
"value": {
|
|
||||||
"kind": "literal",
|
|
||||||
"type": "Int"
|
|
||||||
},
|
|
||||||
"focus": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const lambda2Params: ExprBlockState = {
|
export const lambda2Params: ExprBlockState = {
|
||||||
"kind": "let",
|
"kind": "let",
|
||||||
|
|
|
||||||
40
src/eval.ts
40
src/eval.ts
|
|
@ -1,8 +1,10 @@
|
||||||
import { dict, Double, fnType, getHumanReadableName, getSymbol, Int, mergeUnifications, NotAFunctionError, occurring, prettyT, prettyU, recomputeTypeVars, reduceUnification, substitute, symbolFunction, trie, TYPE_VARS, UNBOUND_SYMBOLS, UnifyError, unifyLL } from "dope2";
|
import { Double, fnType, getHumanReadableName, getSymbol, Int, mergeUnifications, NotAFunctionError, occurring, prettyT, prettyU, recomputeTypeVars, reduceUnification, substitute, symbolFunction, trie, TYPE_VARS, UNBOUND_SYMBOLS, UnifyError, unifyLL, transitivelyGrow } from "dope2";
|
||||||
|
|
||||||
import type { ExprBlockState } from "./ExprBlock";
|
import type { ExprBlockState } from "./ExprBlock";
|
||||||
import type { InputValueType } from "./InputBlock";
|
import type { InputValueType } from "./InputBlock";
|
||||||
|
|
||||||
|
const IS_DEV = (import.meta.env.MODE === "development");
|
||||||
|
|
||||||
export interface Environment {
|
export interface Environment {
|
||||||
names: any;
|
names: any;
|
||||||
nextFreeTypeVar: number;
|
nextFreeTypeVar: number;
|
||||||
|
|
@ -88,30 +90,38 @@ export function evalCallBlock2(fnResolved: ResolvedType, inputResolved: Resolved
|
||||||
try {
|
try {
|
||||||
// fn is a function...
|
// fn is a function...
|
||||||
const [rewrittenFnType] = recomputeTypeVars([fnResolved.t], env.nextFreeTypeVar);
|
const [rewrittenFnType] = recomputeTypeVars([fnResolved.t], env.nextFreeTypeVar);
|
||||||
const unification = unifyLL(rewrittenFnType.params[0](rewrittenFnType), inputResolved.t);
|
const unification = (unifyLL(rewrittenFnType.params[0](rewrittenFnType), inputResolved.t));
|
||||||
|
|
||||||
const inputTypeVars = occurring(inputResolved.t);
|
const inputTypeVars = occurring(inputResolved.t);
|
||||||
|
const fnTypeVars = occurring(fnResolved.t);
|
||||||
const subsetOfUnification = new Map([...unification].filter(([typeVar]) => inputTypeVars.has(typeVar)));
|
const subsetOfUnification = new Map([...unification].filter(([typeVar]) => inputTypeVars.has(typeVar)));
|
||||||
|
const otherSubSetOfUnification = new Map([...unification].filter(([typeVar]) => fnTypeVars.has(typeVar)));
|
||||||
|
|
||||||
const outType = substitute(
|
const outType = substitute(
|
||||||
rewrittenFnType.params[1](rewrittenFnType),
|
rewrittenFnType.params[1](rewrittenFnType),
|
||||||
reduceUnification(subsetOfUnification),
|
reduceUnification(unification),
|
||||||
[]); // <- not important
|
[]); // <- not important
|
||||||
|
|
||||||
|
const grandUnification = [fnResolved.unification, inputResolved.unification]
|
||||||
|
.reduce(mergeUnifications, unification);
|
||||||
|
|
||||||
|
if (IS_DEV) {
|
||||||
console.log('========= evalCallBlock2 =========')
|
console.log('========= evalCallBlock2 =========')
|
||||||
console.log('fnType :', prettyT(fnResolved.t));
|
console.log('fnType :', prettyT(fnResolved.t));
|
||||||
console.log('rewrittenFnType :', prettyT(rewrittenFnType));
|
console.log('rewrittenFnType :', prettyT(rewrittenFnType));
|
||||||
console.log('inputType :', prettyT(inputResolved.t));
|
console.log('inputType :', prettyT(inputResolved.t));
|
||||||
console.log('outType :', prettyT(outType));
|
|
||||||
console.log('unification :', prettyU(unification));
|
console.log('unification :', prettyU(unification));
|
||||||
console.log('inputTypeVars :', [...inputTypeVars].map(getHumanReadableName));
|
console.log('subsetOfUnification :', prettyU(subsetOfUnification));
|
||||||
|
console.log('otherSubSetOfUnification:', prettyU(otherSubSetOfUnification));
|
||||||
|
console.log('outType :', prettyT(outType));
|
||||||
|
// console.log('inputTypeVars :', `{${[...inputTypeVars].map(getHumanReadableName).join(', ')}}`);
|
||||||
|
// console.log('fnTypeVars :', `{${[...fnTypeVars].map(getHumanReadableName).join(', ')}}`);
|
||||||
console.log('fn.unification :', prettyU(fnResolved.unification));
|
console.log('fn.unification :', prettyU(fnResolved.unification));
|
||||||
console.log('input.unification :', prettyU(inputResolved.unification));
|
console.log('input.unification :', prettyU(inputResolved.unification));
|
||||||
console.log('subsetOfUnification:', prettyU(subsetOfUnification));
|
console.log('grandUnification :', prettyU(grandUnification));
|
||||||
console.log('==================================')
|
console.log('==================================')
|
||||||
|
}
|
||||||
|
|
||||||
const grandUnification = [fnResolved.unification, inputResolved.unification]
|
|
||||||
.reduce(mergeUnifications, subsetOfUnification);
|
|
||||||
|
|
||||||
if (inputResolved.kind === "error") {
|
if (inputResolved.kind === "error") {
|
||||||
return {
|
return {
|
||||||
|
|
@ -155,17 +165,25 @@ export function evalCallBlock2(fnResolved: ResolvedType, inputResolved: Resolved
|
||||||
if ((e instanceof UnifyError)) {
|
if ((e instanceof UnifyError)) {
|
||||||
// even though fn was incompatible with the given parameter, we can still suppose that our output-type will be that of fn...?
|
// even though fn was incompatible with the given parameter, we can still suppose that our output-type will be that of fn...?
|
||||||
const outType = fnResolved.t.params[1](fnResolved.t);
|
const outType = fnResolved.t.params[1](fnResolved.t);
|
||||||
|
try {
|
||||||
return {
|
return {
|
||||||
kind: "error",
|
kind: "error",
|
||||||
e,
|
e,
|
||||||
depth: 0,
|
depth: 0,
|
||||||
t: outType,
|
t: outType,
|
||||||
unification: mergeUnifications(fnResolved.unification, inputResolved.unification),
|
unification: mergeUnifications(fnResolved.unification, inputResolved.unification), // may throw!
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
catch (e) {
|
||||||
|
if ((e instanceof UnifyError)) {
|
||||||
|
return makeError(env, e);
|
||||||
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export function evalCallBlock(fn: ExprBlockState, input: ExprBlockState, env): ResolvedType {
|
export function evalCallBlock(fn: ExprBlockState, input: ExprBlockState, env): ResolvedType {
|
||||||
const fnResolved = evalEditorBlock(fn, env);
|
const fnResolved = evalEditorBlock(fn, env);
|
||||||
|
|
@ -190,12 +208,14 @@ export function evalLambdaBlock(paramName: string, expr: ExprBlockState, env): R
|
||||||
reduceUnification(exprResolved.unification),
|
reduceUnification(exprResolved.unification),
|
||||||
[]); // <- not important
|
[]); // <- not important
|
||||||
|
|
||||||
|
if (IS_DEV) {
|
||||||
console.log('========= evalLambdaBlock =========')
|
console.log('========= evalLambdaBlock =========')
|
||||||
console.log('paramType :', prettyT(paramType));
|
console.log('paramType :', prettyT(paramType));
|
||||||
console.log('exprType :', prettyT(exprResolved.t));
|
console.log('exprType :', prettyT(exprResolved.t));
|
||||||
console.log('lambdaType :', prettyT(lambdaT));
|
console.log('lambdaType :', prettyT(lambdaT));
|
||||||
console.log('lambdaTypeSubsituted:', prettyT(lambdaTSubstituted));
|
console.log('lambdaTypeSubsituted:', prettyT(lambdaTSubstituted));
|
||||||
console.log('===================================')
|
console.log('===================================')
|
||||||
|
}
|
||||||
|
|
||||||
// console.log('inner kind', exprResolved.kind, paramName);
|
// console.log('inner kind', exprResolved.kind, paramName);
|
||||||
if (exprResolved.kind === "error") {
|
if (exprResolved.kind === "error") {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue