include and "include as"

This commit is contained in:
Umur Ozkul 2022-08-31 23:54:54 +02:00
parent 68ddf35387
commit 82a4e52384
15 changed files with 732 additions and 241 deletions

View File

@ -0,0 +1,27 @@
@@warning("-44")
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
module Bindings = Reducer_Bindings
open Jest
open Expect
open Expect.Operators
describe("Name Space", () => {
let value = InternalExpressionValue.IEvNumber(1967.0)
let nameSpace = Bindings.emptyNameSpace->Bindings.set("value", value)
test("get", () => {
expect(Bindings.get(nameSpace, "value")) == Some(value)
})
test("chain and get", () => {
let mainNameSpace = Bindings.emptyNameSpace->Bindings.chainTo([nameSpace])
expect(Bindings.get(mainNameSpace, "value")) == Some(value)
})
test("chain and set", () => {
let mainNameSpace0 = Bindings.emptyNameSpace->Bindings.chainTo([nameSpace])
let mainNameSpace =
mainNameSpace0->Bindings.set("value", InternalExpressionValue.IEvNumber(1968.0))
expect(Bindings.get(mainNameSpace, "value")) == Some(InternalExpressionValue.IEvNumber(1968.0))
})
})

View File

@ -7,7 +7,7 @@ open Jest
open Expect
open Expect.Operators
Only.describe("Parse includes", () => {
describe("Parse includes", () => {
let project = Project.createProject()
Project.setSource(
project,
@ -30,4 +30,92 @@ x=1`,
| Error(error) => fail(error->Reducer_ErrorValue.errorToString)
}
})
let internalProject = project->Project.T.Private.castToInternalProject
test("past chain", () => {
expect(Project.Private.getPastChain(internalProject, "main")) == ["common"]
})
test("import as variables", () => {
expect(Project.Private.getIncludesAsVariables(internalProject, "main")) == []
})
})
describe("Parse includes", () => {
let project = Project.createProject()
Project.setSource(
project,
"main",
`
#include 'common'
#include 'myModule' as myVariable
x=1`,
)
Project.parseIncludes(project, "main")
test("dependencies", () => {
expect(Project.getDependencies(project, "main")) == ["common", "myModule"]
})
test("dependents", () => {
expect(Project.getDependents(project, "main")) == []
})
test("getIncludes", () => {
let mainIncludes = Project.getIncludes(project, "main")
switch mainIncludes {
| Ok(includes) => expect(includes) == ["common", "myModule"]
| Error(error) => fail(error->Reducer_ErrorValue.errorToString)
}
})
let internalProject = project->Project.T.Private.castToInternalProject
test("direct past chain", () => {
expect(Project.Private.getPastChain(internalProject, "main")) == ["common"]
})
test("direct includes", () => {
expect(Project.Private.getDirectIncludes(internalProject, "main")) == ["common"]
})
test("include as variables", () => {
expect(Project.Private.getIncludesAsVariables(internalProject, "main")) == [
("myVariable", "myModule"),
]
})
})
describe("Parse multiple direct includes", () => {
let project = Project.createProject()
Project.setSource(
project,
"main",
`
#include 'common'
#include 'common2'
#include 'myModule' as myVariable
x=1`,
)
Project.parseIncludes(project, "main")
test("dependencies", () => {
expect(Project.getDependencies(project, "main")) == ["common", "common2", "myModule"]
})
test("dependents", () => {
expect(Project.getDependents(project, "main")) == []
})
test("getIncludes", () => {
let mainIncludes = Project.getIncludes(project, "main")
switch mainIncludes {
| Ok(includes) => expect(includes) == ["common", "common2", "myModule"]
| Error(error) => fail(error->Reducer_ErrorValue.errorToString)
}
})
let internalProject = project->Project.T.Private.castToInternalProject
test("direct past chain", () => {
expect(Project.getPastChain(project, "main")) == ["common", "common2"]
})
test("include as variables", () => {
expect(Project.Private.getIncludesAsVariables(internalProject, "main")) == [
("myVariable", "myModule"),
]
})
})

View File

@ -14,11 +14,9 @@ let runFetchResult = (project, sourceId) => {
Project.getResult(project, sourceId)->InternalExpressionValue.toStringResult
}
let runFetchBindings = (project, sourceId) => {
let runFetchFlatBindings = (project, sourceId) => {
Project.run(project, sourceId)
Project.getBindings(project, sourceId)
->InternalExpressionValue.IEvBindings
->InternalExpressionValue.toString
Project.getBindings(project, sourceId)->InternalExpressionValue.toStringBindings
}
test("setting continuation", () => {
@ -51,7 +49,7 @@ test("test library", () => {
test("test bindings", () => {
let project = Project.createProject()
Project.setSource(project, "variables", "myVariable=666")
runFetchBindings(project, "variables")->expect->toBe("@{myVariable: 666}")
runFetchFlatBindings(project, "variables")->expect->toBe("@{myVariable: 666}")
})
describe("project1", () => {
@ -59,6 +57,7 @@ describe("project1", () => {
Project.setSource(project, "first", "x=1")
Project.setSource(project, "main", "x")
Project.setContinues(project, "main", ["first"])
let internalProject = project->Project.T.Private.castToInternalProject
test("runOrder", () => {
expect(Project.getRunOrder(project)) == ["first", "main"]
@ -75,11 +74,19 @@ describe("project1", () => {
test("dependencies main", () => {
expect(Project.getDependencies(project, "main")) == ["first"]
})
test("past chain first", () => {
expect(Project.Private.getPastChain(internalProject, "first")) == []
})
test("past chain main", () => {
expect(Project.Private.getPastChain(internalProject, "main")) == ["first"]
})
test("test result", () => {
runFetchResult(project, "main")->expect->toBe("Ok(1)")
})
test("test bindings", () => {
runFetchBindings(project, "main")->expect->toBe("@{x: 1}")
runFetchFlatBindings(project, "first")->expect->toBe("@{x: 1}")
})
})
@ -113,7 +120,7 @@ describe("project2", () => {
runFetchResult(project, "main")->expect->toBe("Ok(2)")
})
test("test bindings", () => {
runFetchBindings(project, "main")->expect->toBe("@{x: 1,y: 2}")
runFetchFlatBindings(project, "main")->expect->toBe("@{x: 1,y: 2}")
})
})
@ -169,6 +176,6 @@ describe("project with include", () => {
runFetchResult(project, "main")->expect->toBe("Ok(2)")
})
test("test bindings", () => {
runFetchBindings(project, "main")->expect->toBe("@{common: 0,x: 1,y: 2}")
runFetchFlatBindings(project, "main")->expect->toBe("@{common: 0,x: 1,y: 2}")
})
})

View File

@ -153,4 +153,27 @@ Here we will finally proceed to a real life scenario. */
})
})
})
describe("Includes myFile as myVariable", () => {
/* Instead of including into global space you can also put a module into a record variable */
let project = Project.createProject()
Project.setSource(
project,
"main",
`
#include "common" as common
x=1
`,
)
Project.parseIncludes(project, "main")
test("getDependencies", () => {
Project.getDependencies(project, "main")->expect == ["common"]
})
test("getIncludes", () => {
switch Project.getIncludes(project, "main") {
| Ok(includes) => includes->expect == ["common"]
| Error(err) => err->Reducer_ErrorValue.errorToString->fail
}
})
})
})

View File

@ -105,6 +105,11 @@ let getIncludes = (project: reducerProject, sourceId: string): result<
reducerErrorValue,
> => project->T.Private.castToInternalProject->Private.getIncludes(sourceId)
/* Other sources contributing to the global namespace of this source. */
@genType
let getPastChain = (project: reducerProject, sourceId: string): array<string> =>
project->T.Private.castToInternalProject->Private.getPastChain(sourceId)
/*
Answers the source codes after which this source code is continuing
*/
@ -183,7 +188,7 @@ let runAll = (project: reducerProject): unit =>
project->T.Private.castToInternalProject->Private.runAll
/*
Get the bindings after running this source file or the project
Get the bindings after running this source fil. The bindings are local to the source
*/
@genType
let getBindings = (project: reducerProject, sourceId: string): squiggleValue_Module =>

View File

@ -1,5 +1,5 @@
// Only Bindings as the global module is supported
// Other module operations such as import export will be prepreocessed jobs
// Other module operations such as import export will be preprocessed jobs
module ExpressionT = Reducer_Expression_T
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
@ -13,8 +13,7 @@ type t = ReducerInterface_InternalExpressionValue.nameSpace
let typeAliasesKey = "_typeAliases_"
let typeReferencesKey = "_typeReferences_"
let getType = (nameSpace: t, id: string) => {
let NameSpace(container) = nameSpace
let getType = (NameSpace(container): t, id: string) => {
Belt.Map.String.get(container, typeAliasesKey)->Belt.Option.flatMap(aliases =>
switch aliases {
| IEvRecord(r) => Belt.Map.String.get(r, id)
@ -23,8 +22,7 @@ let getType = (nameSpace: t, id: string) => {
)
}
let getTypeOf = (nameSpace: t, id: string) => {
let NameSpace(container) = nameSpace
let getTypeOf = (NameSpace(container): t, id: string) => {
Belt.Map.String.get(container, typeReferencesKey)->Belt.Option.flatMap(defs =>
switch defs {
| IEvRecord(r) => Belt.Map.String.get(r, id)
@ -33,44 +31,39 @@ let getTypeOf = (nameSpace: t, id: string) => {
)
}
let getWithDefault = (nameSpace: t, id: string, default) => {
let NameSpace(container) = nameSpace
Belt.Map.String.getWithDefault(container, id, default)
let getWithDefault = (NameSpace(container): t, id: string, default) =>
switch Belt.Map.String.get(container, id) {
| Some(v) => v
| None => default
}
let get = (nameSpace: t, id: string) => {
let NameSpace(container) = nameSpace
Belt.Map.String.get(container, id)
}
let get = (NameSpace(container): t, id: string) => Belt.Map.String.get(container, id)
let emptyMap: map = Belt.Map.String.empty
let setTypeAlias = (nameSpace: t, id: string, value): t => {
let NameSpace(container) = nameSpace
let setTypeAlias = (NameSpace(container): t, id: string, value): t => {
let rValue = Belt.Map.String.getWithDefault(container, typeAliasesKey, IEvRecord(emptyMap))
let r = switch rValue {
| IEvRecord(r) => r
| _ => emptyMap
}
let r2 = Belt.Map.String.set(r, id, value)->IEvRecord
Belt.Map.String.set(container, typeAliasesKey, r2)->NameSpace
NameSpace(Belt.Map.String.set(container, typeAliasesKey, r2))
}
let setTypeOf = (nameSpace: t, id: string, value): t => {
let NameSpace(container) = nameSpace
let setTypeOf = (NameSpace(container): t, id: string, value): t => {
let rValue = Belt.Map.String.getWithDefault(container, typeReferencesKey, IEvRecord(emptyMap))
let r = switch rValue {
| IEvRecord(r) => r
| _ => emptyMap
}
let r2 = Belt.Map.String.set(r, id, value)->IEvRecord
Belt.Map.String.set(container, typeReferencesKey, r2)->NameSpace
NameSpace(Belt.Map.String.set(container, typeReferencesKey, r2))
}
let set = (nameSpace: t, id: string, value): t => {
let NameSpace(container) = nameSpace
Belt.Map.String.set(container, id, value)->NameSpace
}
let set = (NameSpace(container): t, id: string, value): t => NameSpace(
Belt.Map.String.set(container, id, value),
)
let emptyModule: t = NameSpace(emptyMap)
let emptyBindings = emptyModule
@ -86,29 +79,28 @@ let fromExpressionValue = (aValue: internalExpressionValue): t =>
| _ => emptyModule
}
let fromArray = a => Belt.Map.String.fromArray(a)->NameSpace
let fromArray = a => NameSpace(Belt.Map.String.fromArray(a))
let merge = (nameSpace: t, other: t): t => {
let NameSpace(container) = nameSpace
let NameSpace(otherContainer) = other
otherContainer
->Belt.Map.String.reduce(container, (container, key, value) =>
let mergeFrom = (NameSpace(container): t, NameSpace(newContainer): t): t => {
NameSpace(
newContainer->Belt.Map.String.reduce(container, (container, key, value) =>
Belt.Map.String.set(container, key, value)
),
)
->NameSpace
}
let removeOther = (nameSpace: t, other: t): t => {
let NameSpace(container) = nameSpace
let NameSpace(otherContainer) = other
let removeOther = (NameSpace(container): t, NameSpace(otherContainer): t): t => {
let keys = Belt.Map.String.keysToArray(otherContainer)
NameSpace(
Belt.Map.String.keep(container, (key, _value) => {
let removeThis = Js.Array2.includes(keys, key)
!removeThis
})->NameSpace
}),
)
}
external castExpressionToInternalCode: ExpressionT.expressionOrFFI => internalCode = "%identity"
let eLambdaFFIValue = (ffiFn: ExpressionT.ffiFn) => {
IEvLambda({
parameters: [],
@ -153,9 +145,8 @@ let convertOptionToFfiFn = (
}
// -- Module definition
let define = (nameSpace: t, identifier: string, ev: internalExpressionValue): t => {
let NameSpace(container) = nameSpace
Belt.Map.String.set(container, identifier, ev)->NameSpace
let define = (NameSpace(container): t, identifier: string, ev: internalExpressionValue): t => {
NameSpace(Belt.Map.String.set(container, identifier, ev))
}
let defineNumber = (nameSpace: t, identifier: string, value: float): t =>
@ -186,3 +177,9 @@ let defineFunctionReturningResult = (
}
let emptyStdLib: t = emptyModule->defineBool("_standardLibrary", true)
let chainTo = (nameSpace: t, previousNameSpaces: array<t>) => {
previousNameSpaces->Belt.Array.reduce(nameSpace, (topNameSpace, prevNameSpace) =>
mergeFrom(prevNameSpace, topNameSpace)
)
}

View File

@ -21,8 +21,7 @@ let inspectOption = (oNameSpace, label: string) =>
}
let minus = (NameSpace(thisContainer): t, NameSpace(thatContainer): t) => {
Belt.Map.String.removeMany(
thisContainer,
Belt.Map.String.keysToArray(thatContainer),
)->InternalExpressionValue.NameSpace
InternalExpressionValue.NameSpace(
Belt.Map.String.removeMany(thisContainer, Belt.Map.String.keysToArray(thatContainer)),
)
}

View File

@ -83,6 +83,21 @@ module Private = {
let getIncludes = (project: t, sourceId: string): ProjectItem.T.includesType =>
project->getItem(sourceId)->ProjectItem.getIncludes
// let getDirectIncludes = (project: t, sourceId: string): array<string> =>
// project->getItem(sourceId)->ProjectItem.getDirectIncludes
let getPastChain = (project: t, sourceId: string): array<string> =>
project->getItem(sourceId)->ProjectItem.getPastChain
let getIncludesAsVariables = (
project: t,
sourceId: string,
): ProjectItem.T.importAsVariablesType =>
project->getItem(sourceId)->ProjectItem.getIncludesAsVariables
let getDirectIncludes = (project: t, sourceId: string): array<string> =>
project->getItem(sourceId)->ProjectItem.getDirectIncludes
let setContinues = (project: t, sourceId: string, continues: array<string>): unit => {
let newItem = project->getItem(sourceId)->ProjectItem.setContinues(continues)
Belt.Map.String.set(project["items"], sourceId, newItem)->T.Private.setFieldItems(project, _)
@ -155,39 +170,63 @@ module Private = {
environment: getEnvironment(project),
}
let doRunWithContinuation = (
project: t,
sourceId: string,
continuation: ProjectItem.T.continuation,
): unit => {
let getContinuationsBefore = (project: t, sourceId: string): array<
ProjectItem.T.continuation,
> => {
let pastNameSpaces = project->getPastChain(sourceId)->Belt.Array.map(getBindings(project, _))
let theLength = Belt.Array.length(pastNameSpaces)
if theLength == 0 {
// `getContinuationBefore ${sourceId}: stdLib`->Js.log
[project->getStdLib]
} else {
// `getContinuationBefore ${sourceId}: ${lastOne} = ${InternalExpressionValue.toStringBindings(
// project->getBindings(lastOne),
// )}`->Js.log
pastNameSpaces
}
}
let linkDependencies = (project: t, sourceId: string): ProjectItem.T.continuation => {
module NameSpace = Reducer_Bindings
let continuationsBefore = project->getContinuationsBefore(sourceId)
let nameSpace = NameSpace.emptyNameSpace->NameSpace.chainTo(continuationsBefore)
let includesAsVariables = project->getIncludesAsVariables(sourceId)
Belt.Array.reduce(includesAsVariables, nameSpace, (currentNameSpace, (variable, includeFile)) =>
Bindings.set(
currentNameSpace,
variable,
getBindings(project, includeFile)->InternalExpressionValue.IEvBindings,
)
)
}
let doLinkAndRun = (project: t, sourceId: string): unit => {
let accessors = buildProjectAccessors(project)
let states = accessors.states
let continuation = linkDependencies(project, sourceId)
let newItem = project->getItem(sourceId)->ProjectItem.run(continuation, accessors)
Belt.Map.String.set(project["items"], sourceId, newItem)->T.Private.setFieldItems(project, _)
setContinuation(project, sourceId, states.continuation)
}
type runState = (ProjectItem.T.resultArgumentType, ProjectItem.T.continuation)
type runState = ProjectItem.T.resultArgumentType
let tryRunWithContinuation = (
let tryRunWithResult = (
project: t,
sourceId: string,
(rPrevResult: ProjectItem.T.resultArgumentType, continuation: ProjectItem.T.continuation),
): (ProjectItem.T.resultArgumentType, ProjectItem.T.continuation) => {
rPrevResult: ProjectItem.T.resultArgumentType,
): ProjectItem.T.resultArgumentType => {
switch getResultOption(project, sourceId) {
| Some(result) => (result, getContinuation(project, sourceId)) // already ran
| Some(result) => result // already ran
| None =>
switch rPrevResult {
| Error(error) => {
setResult(project, sourceId, Error(error))
(Error(error), continuation)
Error(error)
}
| Ok(_prevResult) => {
doRunWithContinuation(project, sourceId, continuation)
(
getResultOption(project, sourceId)->Belt.Option.getWithDefault(rPrevResult),
getContinuation(project, sourceId),
)
doLinkAndRun(project, sourceId)
getResultOption(project, sourceId)->Belt.Option.getWithDefault(rPrevResult)
}
}
}
@ -195,17 +234,17 @@ module Private = {
let runAll = (project: t): unit => {
let runOrder = Topology.getRunOrder(project)
let initialState = (Ok(InternalExpressionValue.IEvVoid), getStdLib(project))
let initialState = Ok(InternalExpressionValue.IEvVoid)
let _finalState = Belt.Array.reduce(runOrder, initialState, (currState, currId) =>
tryRunWithContinuation(project, currId, currState)
tryRunWithResult(project, currId, currState)
)
}
let run = (project: t, sourceId: string): unit => {
let runOrder = Topology.getRunOrderFor(project, sourceId)
let initialState = (Ok(InternalExpressionValue.IEvVoid), getStdLib(project))
let initialState = Ok(InternalExpressionValue.IEvVoid)
let _finalState = Belt.Array.reduce(runOrder, initialState, (currState, currId) =>
tryRunWithContinuation(project, currId, currState)
tryRunWithResult(project, currId, currState)
)
}

View File

@ -173,12 +173,14 @@ function peg$parse(input, options) {
var peg$startRuleFunctions = { start: peg$parsestart };
var peg$startRuleFunction = peg$parsestart;
var peg$c0 = "#include";
var peg$c1 = "'";
var peg$c2 = "\"";
var peg$c3 = "//";
var peg$c4 = "/*";
var peg$c5 = "*/";
var peg$c0 = "#";
var peg$c1 = "#include";
var peg$c2 = "as";
var peg$c3 = "'";
var peg$c4 = "\"";
var peg$c5 = "//";
var peg$c6 = "/*";
var peg$c7 = "*/";
var peg$r0 = /^[^']/;
var peg$r1 = /^[^"]/;
@ -186,29 +188,40 @@ function peg$parse(input, options) {
var peg$r3 = /^[ \t]/;
var peg$r4 = /^[\n\r]/;
var peg$r5 = /^[^\r\n]/;
var peg$r6 = /^[_a-z]/;
var peg$r7 = /^[_a-z0-9]/i;
var peg$e0 = peg$literalExpectation("#include", false);
var peg$e1 = peg$otherExpectation("string");
var peg$e2 = peg$literalExpectation("'", false);
var peg$e3 = peg$classExpectation(["'"], true, false);
var peg$e4 = peg$literalExpectation("\"", false);
var peg$e5 = peg$classExpectation(["\""], true, false);
var peg$e6 = peg$literalExpectation("//", false);
var peg$e7 = peg$literalExpectation("/*", false);
var peg$e8 = peg$classExpectation(["*"], true, false);
var peg$e9 = peg$literalExpectation("*/", false);
var peg$e10 = peg$otherExpectation("white space");
var peg$e11 = peg$classExpectation([" ", "\t"], false, false);
var peg$e12 = peg$otherExpectation("newline");
var peg$e13 = peg$classExpectation(["\n", "\r"], false, false);
var peg$e14 = peg$classExpectation(["\r", "\n"], true, false);
var peg$e0 = peg$literalExpectation("#", false);
var peg$e1 = peg$literalExpectation("#include", false);
var peg$e2 = peg$literalExpectation("as", false);
var peg$e3 = peg$otherExpectation("string");
var peg$e4 = peg$literalExpectation("'", false);
var peg$e5 = peg$classExpectation(["'"], true, false);
var peg$e6 = peg$literalExpectation("\"", false);
var peg$e7 = peg$classExpectation(["\""], true, false);
var peg$e8 = peg$otherExpectation("comment");
var peg$e9 = peg$literalExpectation("//", false);
var peg$e10 = peg$literalExpectation("/*", false);
var peg$e11 = peg$classExpectation(["*"], true, false);
var peg$e12 = peg$literalExpectation("*/", false);
var peg$e13 = peg$otherExpectation("white space");
var peg$e14 = peg$classExpectation([" ", "\t"], false, false);
var peg$e15 = peg$otherExpectation("newline");
var peg$e16 = peg$classExpectation(["\n", "\r"], false, false);
var peg$e17 = peg$otherExpectation("code");
var peg$e18 = peg$classExpectation(["\r", "\n"], true, false);
var peg$e19 = peg$otherExpectation("identifier");
var peg$e20 = peg$classExpectation(["_", ["a", "z"]], false, false);
var peg$e21 = peg$classExpectation(["_", ["a", "z"], ["0", "9"]], false, true);
var peg$f0 = function(head, tail) {return [head, ...tail].filter( e => e != '');};
var peg$f1 = function() {return [];};
var peg$f2 = function(characters) {return characters.join('');};
var peg$f2 = function(file, variable) {return [!variable ? '' : variable, file]};
var peg$f3 = function(characters) {return characters.join('');};
var peg$f4 = function() { return '';};
var peg$f4 = function(characters) {return characters.join('');};
var peg$f5 = function() { return '';};
var peg$f6 = function() { return '';};
var peg$f7 = function() {return text();};
var peg$currPos = 0;
var peg$savedPos = 0;
var peg$posDetailsCache = [{ line: 1, column: 1 }];
@ -369,7 +382,7 @@ function peg$parse(input, options) {
function peg$parsestart() {
var s0, s1, s2, s3, s4;
var key = peg$currPos * 10 + 0;
var key = peg$currPos * 12 + 0;
var cached = peg$resultsCache[key];
if (cached) {
@ -426,7 +439,7 @@ function peg$parse(input, options) {
function peg$parseincludes() {
var s0, s1, s2, s3, s4, s5;
var key = peg$currPos * 10 + 1;
var key = peg$currPos * 12 + 1;
var cached = peg$resultsCache[key];
if (cached) {
@ -436,7 +449,7 @@ function peg$parse(input, options) {
}
s0 = peg$currPos;
s1 = peg$parseincludeStatement();
s1 = peg$parsedependencyStatement();
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$currPos;
@ -451,7 +464,7 @@ function peg$parse(input, options) {
s4 = peg$FAILED;
}
if (s4 !== peg$FAILED) {
s5 = peg$parseincludeStatement();
s5 = peg$parsedependencyStatement();
if (s5 !== peg$FAILED) {
s3 = s5;
} else {
@ -476,7 +489,7 @@ function peg$parse(input, options) {
s4 = peg$FAILED;
}
if (s4 !== peg$FAILED) {
s5 = peg$parseincludeStatement();
s5 = peg$parsedependencyStatement();
if (s5 !== peg$FAILED) {
s3 = s5;
} else {
@ -496,9 +509,26 @@ function peg$parse(input, options) {
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$parseignore();
s1 = peg$currPos;
peg$silentFails++;
if (input.charCodeAt(peg$currPos) === 35) {
s2 = peg$c0;
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e0); }
}
peg$silentFails--;
if (s2 === peg$FAILED) {
s1 = undefined;
} else {
peg$currPos = s1;
s1 = peg$FAILED;
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
s1 = peg$f1();
}
s0 = s1;
}
@ -507,10 +537,35 @@ function peg$parse(input, options) {
return s0;
}
function peg$parseincludeStatement() {
var s0, s1, s2, s3, s4, s5, s6;
function peg$parsedependencyStatement() {
var s0;
var key = peg$currPos * 10 + 2;
var key = peg$currPos * 12 + 2;
var cached = peg$resultsCache[key];
if (cached) {
peg$currPos = cached.nextPos;
return cached.result;
}
s0 = peg$parseincludeStatement();
if (s0 === peg$FAILED) {
s0 = peg$parsecomment();
if (s0 === peg$FAILED) {
s0 = peg$parsedelimitedComment();
}
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
return s0;
}
function peg$parseincludeStatement() {
var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;
var key = peg$currPos * 12 + 3;
var cached = peg$resultsCache[key];
if (cached) {
@ -526,29 +581,99 @@ function peg$parse(input, options) {
s1.push(s2);
s2 = peg$parse_();
}
if (input.substr(peg$currPos, 8) === peg$c0) {
s2 = peg$c0;
if (input.substr(peg$currPos, 8) === peg$c1) {
s2 = peg$c1;
peg$currPos += 8;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e0); }
if (peg$silentFails === 0) { peg$fail(peg$e1); }
}
if (s2 !== peg$FAILED) {
s3 = [];
s4 = peg$parse_();
if (s4 !== peg$FAILED) {
while (s4 !== peg$FAILED) {
s3.push(s4);
s4 = peg$parse_();
}
} else {
s3 = peg$FAILED;
}
if (s3 !== peg$FAILED) {
s4 = peg$parsestring();
if (s4 !== peg$FAILED) {
s5 = [];
s6 = peg$parse_();
while (s6 !== peg$FAILED) {
s5.push(s6);
s6 = peg$parse_();
s5 = peg$currPos;
s6 = [];
s7 = peg$parse_();
if (s7 !== peg$FAILED) {
while (s7 !== peg$FAILED) {
s6.push(s7);
s7 = peg$parse_();
}
s0 = s4;
} else {
s6 = peg$FAILED;
}
if (s6 !== peg$FAILED) {
if (input.substr(peg$currPos, 2) === peg$c2) {
s7 = peg$c2;
peg$currPos += 2;
} else {
s7 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e2); }
}
if (s7 !== peg$FAILED) {
s8 = [];
s9 = peg$parse_();
if (s9 !== peg$FAILED) {
while (s9 !== peg$FAILED) {
s8.push(s9);
s9 = peg$parse_();
}
} else {
s8 = peg$FAILED;
}
if (s8 !== peg$FAILED) {
s9 = peg$parseidentifier();
if (s9 !== peg$FAILED) {
s5 = s9;
} else {
peg$currPos = s5;
s5 = peg$FAILED;
}
} else {
peg$currPos = s5;
s5 = peg$FAILED;
}
} else {
peg$currPos = s5;
s5 = peg$FAILED;
}
} else {
peg$currPos = s5;
s5 = peg$FAILED;
}
if (s5 === peg$FAILED) {
s5 = null;
}
s6 = [];
s7 = peg$parse_();
while (s7 !== peg$FAILED) {
s6.push(s7);
s7 = peg$parse_();
}
s7 = peg$currPos;
peg$silentFails++;
s8 = peg$parsenewLine();
peg$silentFails--;
if (s8 !== peg$FAILED) {
peg$currPos = s7;
s7 = undefined;
} else {
s7 = peg$FAILED;
}
if (s7 !== peg$FAILED) {
peg$savedPos = s0;
s0 = peg$f2(s4, s5);
} else {
peg$currPos = s0;
s0 = peg$FAILED;
@ -557,11 +682,13 @@ function peg$parse(input, options) {
peg$currPos = s0;
s0 = peg$FAILED;
}
if (s0 === peg$FAILED) {
s0 = peg$parsecomment();
if (s0 === peg$FAILED) {
s0 = peg$parsedelimitedComment();
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -572,7 +699,7 @@ function peg$parse(input, options) {
function peg$parsestring() {
var s0, s1, s2, s3, s4;
var key = peg$currPos * 10 + 3;
var key = peg$currPos * 12 + 4;
var cached = peg$resultsCache[key];
if (cached) {
@ -585,58 +712,7 @@ function peg$parse(input, options) {
s0 = peg$currPos;
s1 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 39) {
s2 = peg$c1;
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e2); }
}
if (s2 !== peg$FAILED) {
s3 = [];
if (peg$r0.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e3); }
}
while (s4 !== peg$FAILED) {
s3.push(s4);
if (peg$r0.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e3); }
}
}
if (input.charCodeAt(peg$currPos) === 39) {
s4 = peg$c1;
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e2); }
}
if (s4 !== peg$FAILED) {
s1 = s3;
} else {
peg$currPos = s1;
s1 = peg$FAILED;
}
} else {
peg$currPos = s1;
s1 = peg$FAILED;
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
s1 = peg$f2(s1);
}
s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 34) {
s2 = peg$c2;
s2 = peg$c3;
peg$currPos++;
} else {
s2 = peg$FAILED;
@ -644,7 +720,7 @@ function peg$parse(input, options) {
}
if (s2 !== peg$FAILED) {
s3 = [];
if (peg$r1.test(input.charAt(peg$currPos))) {
if (peg$r0.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
@ -653,7 +729,7 @@ function peg$parse(input, options) {
}
while (s4 !== peg$FAILED) {
s3.push(s4);
if (peg$r1.test(input.charAt(peg$currPos))) {
if (peg$r0.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
@ -661,8 +737,8 @@ function peg$parse(input, options) {
if (peg$silentFails === 0) { peg$fail(peg$e5); }
}
}
if (input.charCodeAt(peg$currPos) === 34) {
s4 = peg$c2;
if (input.charCodeAt(peg$currPos) === 39) {
s4 = peg$c3;
peg$currPos++;
} else {
s4 = peg$FAILED;
@ -683,11 +759,62 @@ function peg$parse(input, options) {
s1 = peg$f3(s1);
}
s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 34) {
s2 = peg$c4;
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e6); }
}
if (s2 !== peg$FAILED) {
s3 = [];
if (peg$r1.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e7); }
}
while (s4 !== peg$FAILED) {
s3.push(s4);
if (peg$r1.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e7); }
}
}
if (input.charCodeAt(peg$currPos) === 34) {
s4 = peg$c4;
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e6); }
}
if (s4 !== peg$FAILED) {
s1 = s3;
} else {
peg$currPos = s1;
s1 = peg$FAILED;
}
} else {
peg$currPos = s1;
s1 = peg$FAILED;
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
s1 = peg$f4(s1);
}
s0 = s1;
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e1); }
if (peg$silentFails === 0) { peg$fail(peg$e3); }
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -698,7 +825,7 @@ function peg$parse(input, options) {
function peg$parseignore() {
var s0, s1;
var key = peg$currPos * 10 + 4;
var key = peg$currPos * 12 + 5;
var cached = peg$resultsCache[key];
if (cached) {
@ -732,9 +859,9 @@ function peg$parse(input, options) {
}
function peg$parsecomment() {
var s0, s1, s2, s3;
var s0, s1, s2, s3, s4;
var key = peg$currPos * 10 + 5;
var key = peg$currPos * 12 + 6;
var cached = peg$resultsCache[key];
if (cached) {
@ -743,79 +870,32 @@ function peg$parse(input, options) {
return cached.result;
}
peg$silentFails++;
s0 = peg$currPos;
if (input.substr(peg$currPos, 2) === peg$c3) {
s1 = peg$c3;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e6); }
}
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$parseany();
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$parseany();
}
peg$savedPos = s0;
s0 = peg$f4();
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
return s0;
}
function peg$parsedelimitedComment() {
var s0, s1, s2, s3;
var key = peg$currPos * 10 + 6;
var cached = peg$resultsCache[key];
if (cached) {
peg$currPos = cached.nextPos;
return cached.result;
}
s0 = peg$currPos;
if (input.substr(peg$currPos, 2) === peg$c4) {
s1 = peg$c4;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e7); }
}
if (s1 !== peg$FAILED) {
s2 = [];
if (peg$r2.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e8); }
}
while (s3 !== peg$FAILED) {
s2.push(s3);
if (peg$r2.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e8); }
}
}
if (input.substr(peg$currPos, 2) === peg$c5) {
s3 = peg$c5;
s1 = peg$c5;
peg$currPos += 2;
} else {
s3 = peg$FAILED;
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e9); }
}
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$parseany();
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$parseany();
}
s3 = peg$currPos;
peg$silentFails++;
s4 = peg$parsenewLine();
peg$silentFails--;
if (s4 !== peg$FAILED) {
peg$currPos = s3;
s3 = undefined;
} else {
s3 = peg$FAILED;
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
s0 = peg$f5();
@ -827,6 +907,80 @@ function peg$parse(input, options) {
peg$currPos = s0;
s0 = peg$FAILED;
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e8); }
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
return s0;
}
function peg$parsedelimitedComment() {
var s0, s1, s2, s3;
var key = peg$currPos * 12 + 7;
var cached = peg$resultsCache[key];
if (cached) {
peg$currPos = cached.nextPos;
return cached.result;
}
peg$silentFails++;
s0 = peg$currPos;
if (input.substr(peg$currPos, 2) === peg$c6) {
s1 = peg$c6;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e10); }
}
if (s1 !== peg$FAILED) {
s2 = [];
if (peg$r2.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e11); }
}
while (s3 !== peg$FAILED) {
s2.push(s3);
if (peg$r2.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e11); }
}
}
if (input.substr(peg$currPos, 2) === peg$c7) {
s3 = peg$c7;
peg$currPos += 2;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e12); }
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
s0 = peg$f6();
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e8); }
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -836,7 +990,7 @@ function peg$parse(input, options) {
function peg$parse_() {
var s0, s1;
var key = peg$currPos * 10 + 7;
var key = peg$currPos * 12 + 8;
var cached = peg$resultsCache[key];
if (cached) {
@ -851,12 +1005,12 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e11); }
if (peg$silentFails === 0) { peg$fail(peg$e14); }
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e10); }
if (peg$silentFails === 0) { peg$fail(peg$e13); }
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -867,7 +1021,7 @@ function peg$parse(input, options) {
function peg$parsenewLine() {
var s0, s1;
var key = peg$currPos * 10 + 8;
var key = peg$currPos * 12 + 9;
var cached = peg$resultsCache[key];
if (cached) {
@ -882,12 +1036,12 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e13); }
if (peg$silentFails === 0) { peg$fail(peg$e16); }
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e12); }
if (peg$silentFails === 0) { peg$fail(peg$e15); }
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -896,9 +1050,9 @@ function peg$parse(input, options) {
}
function peg$parseany() {
var s0;
var s0, s1;
var key = peg$currPos * 10 + 9;
var key = peg$currPos * 12 + 10;
var cached = peg$resultsCache[key];
if (cached) {
@ -907,12 +1061,96 @@ function peg$parse(input, options) {
return cached.result;
}
peg$silentFails++;
if (peg$r5.test(input.charAt(peg$currPos))) {
s0 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e14); }
if (peg$silentFails === 0) { peg$fail(peg$e18); }
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e17); }
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
return s0;
}
function peg$parseidentifier() {
var s0, s1, s2, s3, s4;
var key = peg$currPos * 12 + 11;
var cached = peg$resultsCache[key];
if (cached) {
peg$currPos = cached.nextPos;
return cached.result;
}
peg$silentFails++;
s0 = peg$currPos;
s1 = peg$currPos;
s2 = [];
if (peg$r6.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e20); }
}
if (s3 !== peg$FAILED) {
while (s3 !== peg$FAILED) {
s2.push(s3);
if (peg$r6.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e20); }
}
}
} else {
s2 = peg$FAILED;
}
if (s2 !== peg$FAILED) {
s3 = [];
if (peg$r7.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e21); }
}
while (s4 !== peg$FAILED) {
s3.push(s4);
if (peg$r7.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e21); }
}
}
s2 = [s2, s3];
s1 = s2;
} else {
peg$currPos = s1;
s1 = peg$FAILED;
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
s1 = peg$f7();
}
s0 = s1;
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e19); }
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };

View File

@ -1,33 +1,37 @@
// Includes are at the start of the file, before any other code.
// There might be some comments before or between the includes.
// #include "string"
// #include "string2"
// #include "string2" as aVariable
start
= (newLine/_/comment/delimitedComment)* @includes newLine* ignore
includes
= head:includeStatement tail:(newLine+ @includeStatement)*
= head:dependencyStatement tail:(newLine+ @dependencyStatement)*
{return [head, ...tail].filter( e => e != '');}
/ ignore
/ ! '#'
{return [];}
includeStatement
= _* '#include' _* @string _*
dependencyStatement
= includeStatement
/ comment
/ delimitedComment
includeStatement
= _* '#include' _+ file:string variable:(_+ 'as' _+ @identifier)? _* & newLine
{return [!variable ? '' : variable, file]}
string 'string'
= characters:("'" @([^'])* "'") {return characters.join('');}
/ characters:('"' @([^"])* '"') {return characters.join('');}
ignore = (any / newLine / _)*
comment
= '//'any*
comment 'comment'
= '//'any* & newLine
{ return '';}
delimitedComment
delimitedComment 'comment'
= '/*' ([^*]*) '*/'
{ return '';}
@ -37,4 +41,8 @@ _ "white space"
newLine "newline"
= [\n\r]
any = [^\r\n]
any 'code'
= [^\r\n]
identifier 'identifier'
= ([_a-z]+[_a-z0-9]i*) {return text();}

View File

@ -1,11 +1,15 @@
@module("./ReducerProject_IncludeParser.js") external parse__: string => array<string> = "parse"
@module("./ReducerProject_IncludeParser.js")
external parse__: string => array<array<string>> = "parse"
let parseIncludes = (expr: string): result<array<string>, Reducer_ErrorValue.errorValue> =>
let parseIncludes = (expr: string): result<
array<(string, string)>,
Reducer_ErrorValue.errorValue,
> =>
try {
let answer = parse__(expr)
// let logEntry = answer->Js.Array2.joinWith(",")
// `parseIncludes: ${logEntry} for expr: ${expr}`->Js.log
answer->Ok
Belt.Array.map(answer, item => (item[0], item[1]))->Ok
} catch {
| Js.Exn.Error(obj) =>
RESyntaxError(

View File

@ -19,6 +19,8 @@ let emptyItem = T.ProjectItem({
result: None,
continues: [],
includes: []->Ok,
directIncludes: [],
includeAsVariables: [],
})
// source -> rawParse -> includes -> expression -> continuation -> result
@ -30,40 +32,59 @@ let getResult = (T.ProjectItem(r)): T.resultType => r.result
let getContinues = (T.ProjectItem(r)): T.continuesType => r.continues
let getIncludes = (T.ProjectItem(r)): T.includesType => r.includes
let getDirectIncludes = (T.ProjectItem(r)): array<string> => r.directIncludes
let getIncludesAsVariables = (T.ProjectItem(r)): T.importAsVariablesType => r.includeAsVariables
let touchSource = (this: t): t => {
let T.ProjectItem(r) = emptyItem
T.ProjectItem({
...r,
includes: getIncludes(this),
continues: getContinues(this),
source: getSource(this),
continues: getContinues(this),
includes: getIncludes(this),
includeAsVariables: getIncludesAsVariables(this),
directIncludes: getDirectIncludes(this),
})
}
let touchRawParse = (this: t): t => {
let T.ProjectItem(r) = emptyItem
T.ProjectItem({
...r,
continues: getContinues(this),
source: getSource(this),
rawParse: getRawParse(this),
continues: getContinues(this),
includes: getIncludes(this),
includeAsVariables: getIncludesAsVariables(this),
directIncludes: getDirectIncludes(this),
rawParse: getRawParse(this),
})
}
let touchExpression = (this: t): t => {
let T.ProjectItem(r) = emptyItem
T.ProjectItem({
...r,
continues: getContinues(this),
source: getSource(this),
rawParse: getRawParse(this),
continues: getContinues(this),
includes: getIncludes(this),
includeAsVariables: getIncludesAsVariables(this),
directIncludes: getDirectIncludes(this),
rawParse: getRawParse(this),
expression: getExpression(this),
})
}
let resetIncludes = (T.ProjectItem(r): t): t => {
T.ProjectItem({
...r,
includes: []->Ok,
includeAsVariables: [],
directIncludes: [],
})
}
let setSource = (T.ProjectItem(r): t, source: T.sourceArgumentType): t =>
T.ProjectItem({...r, source: source})->touchSource
T.ProjectItem({...r, source: source})->resetIncludes->touchSource
let setRawParse = (T.ProjectItem(r): t, rawParse: T.rawParseArgumentType): t =>
T.ProjectItem({...r, rawParse: Some(rawParse)})->touchRawParse
@ -95,6 +116,10 @@ let clean = (this: t): t => {
let getImmediateDependencies = (this: t): T.includesType =>
getIncludes(this)->Belt.Result.map(Js.Array2.concat(_, getContinues(this)))
let getPastChain = (this: t): array<string> => {
Js.Array2.concat(getDirectIncludes(this), getContinues(this))
}
let setContinues = (T.ProjectItem(r): t, continues: array<string>): t =>
T.ProjectItem({...r, continues: continues})->touchSource
let removeContinues = (T.ProjectItem(r): t): t => T.ProjectItem({...r, continues: []})->touchSource
@ -104,10 +129,38 @@ let setIncludes = (T.ProjectItem(r): t, includes: T.includesType): t => T.Projec
includes: includes,
})
//TODO: forward parse errors to the user
let parseIncludes = (this: t): t =>
setIncludes(this, getSource(this)->ReducerProject_ParseIncludes.parseIncludes)
let setImportAsVariables = (
T.ProjectItem(r): t,
includeAsVariables: T.importAsVariablesType,
): t => T.ProjectItem({...r, includeAsVariables: includeAsVariables})
let setDirectImports = (T.ProjectItem(r): t, directIncludes: array<string>): t => T.ProjectItem({
...r,
directIncludes: directIncludes,
})
let parseIncludes = (this: t): t => {
let T.ProjectItem(r) = this
let rRawImportAsVariables = getSource(this)->ReducerProject_ParseIncludes.parseIncludes
switch rRawImportAsVariables {
| Error(e) => resetIncludes(this)->setIncludes(Error(e))
| Ok(rawImportAsVariables) => {
let includes = rawImportAsVariables->Belt.Array.map(((_variable, file)) => file)->Ok
let includeAsVariables =
rawImportAsVariables->Belt.Array.keep(((variable, _file)) => variable != "")
let directIncludes =
rawImportAsVariables
->Belt.Array.keep(((variable, _file)) => variable == "")
->Belt.Array.map(((_variable, file)) => file)
T.ProjectItem({
...r,
includes: includes,
includeAsVariables: includeAsVariables,
directIncludes: directIncludes,
})
}
}
}
let doRawParse = (this: t): T.rawParseArgumentType => this->getSource->Reducer_Peggy_Parse.parse
let rawParse = (this: t): t =>

View File

@ -21,6 +21,7 @@ type continuesArgumentType = array<string>
type continuesType = array<string>
type includesArgumentType = string
type includesType = result<array<string>, errorValue>
type importAsVariablesType = array<(string, string)>
type projectItem =
| ProjectItem({
@ -30,7 +31,9 @@ type projectItem =
continuation: continuationArgumentType,
result: resultType,
continues: continuesType,
includes: includesType,
})
includes: includesType, //For loader
includeAsVariables: importAsVariablesType, //For linker
directIncludes: array<string>,
}) //For linker
type t = projectItem

View File

@ -19,4 +19,4 @@ let mathBindings: Bindings.t =
->Bindings.fromArray
let makeBindings = (previousBindings: Bindings.t): Bindings.t =>
previousBindings->Bindings.merge(mathBindings)
previousBindings->Bindings.mergeFrom(mathBindings)

View File

@ -6,4 +6,4 @@ let bindings: Bindings.t =
]->Bindings.fromArray
let makeBindings = (previousBindings: Bindings.t): Bindings.t =>
previousBindings->Bindings.merge(bindings)
previousBindings->Bindings.mergeFrom(bindings)