This commit is contained in:
Kurt Hutten
2023-03-03 20:35:48 +11:00
committed by GitHub
parent 6446601a67
commit 433c29217e
16 changed files with 172 additions and 297 deletions

View File

@ -5,7 +5,6 @@ import { OrbitControls, OrthographicCamera } from '@react-three/drei'
import { asyncLexer } from './lang/tokeniser' import { asyncLexer } from './lang/tokeniser'
import { abstractSyntaxTree } from './lang/abstractSyntaxTree' import { abstractSyntaxTree } from './lang/abstractSyntaxTree'
import { executor, ExtrudeGroup, SketchGroup } from './lang/executor' import { executor, ExtrudeGroup, SketchGroup } from './lang/executor'
import { recast } from './lang/recast'
import CodeMirror from '@uiw/react-codemirror' import CodeMirror from '@uiw/react-codemirror'
import { javascript } from '@codemirror/lang-javascript' import { javascript } from '@codemirror/lang-javascript'
import { ViewUpdate } from '@codemirror/view' import { ViewUpdate } from '@codemirror/view'

View File

@ -1,6 +1,6 @@
import { useStore, toolTips } from './useStore' import { useStore, toolTips } from './useStore'
import { extrudeSketch, sketchOnExtrudedFace } from './lang/modifyAst' import { extrudeSketch, sketchOnExtrudedFace } from './lang/modifyAst'
import { getNodePathFromSourceRange } from './lang/abstractSyntaxTree' import { getNodePathFromSourceRange } from './lang/queryAst'
import { HorzVert } from './components/Toolbar/HorzVert' import { HorzVert } from './components/Toolbar/HorzVert'
import { Equal } from './components/Toolbar/Equal' import { Equal } from './components/Toolbar/Equal'

View File

@ -1,10 +1,6 @@
import { useRef, useState, useEffect, useMemo } from 'react' import { useRef, useState, useEffect, useMemo } from 'react'
import { import { CallExpression, ArrayExpression } from '../lang/abstractSyntaxTree'
getNodePathFromSourceRange, import { getNodePathFromSourceRange, getNodeFromPath } from '../lang/queryAst'
getNodeFromPath,
CallExpression,
ArrayExpression,
} from '../lang/abstractSyntaxTree'
import { changeSketchArguments } from '../lang/std/sketch' import { changeSketchArguments } from '../lang/std/sketch'
import { import {
ExtrudeGroup, ExtrudeGroup,
@ -18,10 +14,9 @@ import {
} from '../lang/executor' } from '../lang/executor'
import { BufferGeometry } from 'three' import { BufferGeometry } from 'three'
import { useStore } from '../useStore' import { useStore } from '../useStore'
import { isOverlap } from '../lib/utils' import { isOverlap, roundOff } from '../lib/utils'
import { Vector3, DoubleSide, Quaternion } from 'three' import { Vector3, DoubleSide, Quaternion } from 'three'
import { useSetCursor } from '../hooks/useSetCursor' import { useSetCursor } from '../hooks/useSetCursor'
import { roundOff } from '../lib/utils'
function MovingSphere({ function MovingSphere({
geo, geo,

View File

@ -1,11 +1,10 @@
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { toolTips, useStore } from '../../useStore' import { toolTips, useStore } from '../../useStore'
import { Value, VariableDeclarator } from '../../lang/abstractSyntaxTree'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,
Value, } from '../../lang/queryAst'
VariableDeclarator,
} from '../../lang/abstractSyntaxTree'
import { isSketchVariablesLinked } from '../../lang/std/sketchConstraints' import { isSketchVariablesLinked } from '../../lang/std/sketchConstraints'
import { import {
TransformInfo, TransformInfo,

View File

@ -1,10 +1,10 @@
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { toolTips, useStore } from '../../useStore' import { toolTips, useStore } from '../../useStore'
import { Value } from '../../lang/abstractSyntaxTree'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,
Value, } from '../../lang/queryAst'
} from '../../lang/abstractSyntaxTree'
import { import {
TransformInfo, TransformInfo,
getTransformInfos, getTransformInfos,

View File

@ -123,7 +123,7 @@ function makeNoneCodeNode(
return { node, lastIndex: endIndex - 1 } return { node, lastIndex: endIndex - 1 }
} }
export function findEndOfNonCodeNode(tokens: Token[], index: number): number { function findEndOfNonCodeNode(tokens: Token[], index: number): number {
const currentToken = tokens[index] const currentToken = tokens[index]
if (isNotCodeToken(currentToken)) { if (isNotCodeToken(currentToken)) {
return findEndOfNonCodeNode(tokens, index + 1) return findEndOfNonCodeNode(tokens, index + 1)
@ -1110,7 +1110,7 @@ function makeReturnStatement(
export type All = Program | ExpressionStatement[] | BinaryExpression | Literal export type All = Program | ExpressionStatement[] | BinaryExpression | Literal
export function nextMeaningfulToken( function nextMeaningfulToken(
tokens: Token[], tokens: Token[],
index: number, index: number,
offset: number = 1 offset: number = 1
@ -1271,7 +1271,7 @@ export const abstractSyntaxTree = (tokens: Token[]): Program => {
return program return program
} }
export function findNextDeclarationKeyword( function findNextDeclarationKeyword(
tokens: Token[], tokens: Token[],
index: number index: number
): { token: Token | null; index: number } { ): { token: Token | null; index: number } {
@ -1300,7 +1300,7 @@ export function findNextDeclarationKeyword(
return findNextDeclarationKeyword(tokens, nextToken.index) return findNextDeclarationKeyword(tokens, nextToken.index)
} }
export function findNextCallExpression( function findNextCallExpression(
tokens: Token[], tokens: Token[],
index: number index: number
): { token: Token | null; index: number } { ): { token: Token | null; index: number } {
@ -1319,7 +1319,7 @@ export function findNextCallExpression(
return findNextCallExpression(tokens, nextToken.index) return findNextCallExpression(tokens, nextToken.index)
} }
export function findNextClosingCurlyBrace( function findNextClosingCurlyBrace(
tokens: Token[], tokens: Token[],
index: number index: number
): { token: Token | null; index: number } { ): { token: Token | null; index: number } {
@ -1447,61 +1447,6 @@ export function findClosingBrace(
return findClosingBrace(tokens, index + 1, _braceCount, searchOpeningBrace) return findClosingBrace(tokens, index + 1, _braceCount, searchOpeningBrace)
} }
// function findOpeningBrace(
// tokens: Token[],
// index: number,
// _braceCount: number = 0,
// _searchClosingBrace: string = ''
// ): number {
// // should be called with the index of the opening brace
// const closingBraceMap: { [key: string]: string } = {
// ')': '(',
// '}': '{',
// ']': '[',
// }
// const currentToken = tokens[index]
// let searchClosingBrace = _searchClosingBrace
// const isFirstCall = !searchClosingBrace && _braceCount === 0
// if (isFirstCall) {
// searchClosingBrace = currentToken.value
// if (![')', '}', ']'].includes(searchClosingBrace)) {
// throw new Error(
// `expected to be started on a opening brace ( { [, instead found '${searchClosingBrace}'`
// )
// }
// }
// const foundOpeningBrace =
// _braceCount === 1 &&
// currentToken.value === closingBraceMap[searchClosingBrace]
// const foundAnotherClosingBrace = currentToken.value === searchClosingBrace
// const foundAnotherOpeningBrace =
// currentToken.value === closingBraceMap[searchClosingBrace]
// if (foundOpeningBrace) {
// return index
// }
// if (foundAnotherClosingBrace) {
// return findOpeningBrace(
// tokens,
// index - 1,
// _braceCount + 1,
// searchClosingBrace
// )
// }
// if (foundAnotherOpeningBrace) {
// return findOpeningBrace(
// tokens,
// index - 1,
// _braceCount - 1,
// searchClosingBrace
// )
// }
// // non-brace token, increment and continue
// return findOpeningBrace(tokens, index - 1, _braceCount, searchClosingBrace)
// }
function isCallExpression(tokens: Token[], index: number): number { function isCallExpression(tokens: Token[], index: number): number {
const currentToken = tokens[index] const currentToken = tokens[index]
const veryNextToken = tokens[index + 1] // i.e. no whitespace const veryNextToken = tokens[index + 1] // i.e. no whitespace
@ -1551,138 +1496,6 @@ function debuggerr(tokens: Token[], indexes: number[], msg = ''): string {
return debugResult return debugResult
} }
export function getNodeFromPath<T>(
node: Program,
path: (string | number)[],
stopAt: string = '',
returnEarly = false
): {
node: T
path: PathToNode
} {
let currentNode = node as any
let stopAtNode = null
let successfulPaths: PathToNode = []
let pathsExplored: PathToNode = []
for (const pathItem of path) {
try {
if (typeof currentNode[pathItem] !== 'object')
throw new Error('not an object')
currentNode = currentNode[pathItem]
successfulPaths.push(pathItem)
if (!stopAtNode) {
pathsExplored.push(pathItem)
}
if (currentNode.type === stopAt) {
// it will match the deepest node of the type
// instead of returning at the first match
stopAtNode = currentNode
if (returnEarly) {
return {
node: stopAtNode,
path: pathsExplored,
}
}
}
} catch (e) {
console.error(
`Could not find path ${pathItem} in node ${JSON.stringify(
currentNode,
null,
2
)}, successful path was ${successfulPaths}`
)
}
}
return {
node: stopAtNode || currentNode,
path: pathsExplored,
}
}
export function getNodeFromPathCurry(
node: Program,
path: (string | number)[]
): <T>(
stopAt: string,
returnEarly?: boolean
) => {
node: T
path: PathToNode
} {
return <T>(stopAt: string = '', returnEarly = false) => {
return getNodeFromPath<T>(node, path, stopAt, returnEarly)
}
}
export function getNodePathFromSourceRange(
node: Program,
sourceRange: Range,
previousPath: PathToNode = []
): PathToNode {
const [start, end] = sourceRange
let path: PathToNode = [...previousPath, 'body']
const _node = { ...node }
// loop over each statement in body getting the index with a for loop
for (
let statementIndex = 0;
statementIndex < _node.body.length;
statementIndex++
) {
const statement = _node.body[statementIndex]
if (statement.start <= start && statement.end >= end) {
path.push(statementIndex)
if (statement.type === 'ExpressionStatement') {
const expression = statement.expression
if (expression.start <= start && expression.end >= end) {
path.push('expression')
if (expression.type === 'CallExpression') {
const callee = expression.callee
if (callee.start <= start && callee.end >= end) {
path.push('callee')
if (callee.type === 'Identifier') {
}
}
}
}
} else if (statement.type === 'VariableDeclaration') {
const declarations = statement.declarations
for (let decIndex = 0; decIndex < declarations.length; decIndex++) {
const declaration = declarations[decIndex]
if (declaration.start <= start && declaration.end >= end) {
path.push('declarations')
path.push(decIndex)
const init = declaration.init
if (init.start <= start && init.end >= end) {
path.push('init')
if (init.type === 'PipeExpression') {
const body = init.body
for (let pipeIndex = 0; pipeIndex < body.length; pipeIndex++) {
const pipe = body[pipeIndex]
if (pipe.start <= start && pipe.end >= end) {
path.push('body')
path.push(pipeIndex)
}
}
} else if (init.type === 'CallExpression') {
const callee = init.callee
if (callee.start <= start && callee.end >= end) {
path.push('callee')
if (callee.type === 'Identifier') {
}
}
}
}
}
}
}
}
}
return path
}
export function isNotCodeToken(token: Token): boolean { export function isNotCodeToken(token: Token): boolean {
return ( return (
token?.type === 'whitespace' || token?.type === 'whitespace' ||

View File

@ -2,10 +2,10 @@ import {
BinaryExpression, BinaryExpression,
Literal, Literal,
Identifier, Identifier,
isNotCodeToken,
findClosingBrace,
CallExpression, CallExpression,
findClosingBrace,
makeCallExpression, makeCallExpression,
isNotCodeToken,
} from './abstractSyntaxTree' } from './abstractSyntaxTree'
import { Token } from './tokeniser' import { Token } from './tokeniser'

View File

@ -1,6 +1,6 @@
import { getNodePathFromSourceRange } from './abstractSyntaxTree' import { getNodePathFromSourceRange, getNodeFromPath } from './queryAst'
import { lexer } from './tokeniser' import { lexer } from './tokeniser'
import { abstractSyntaxTree, getNodeFromPath } from './abstractSyntaxTree' import { abstractSyntaxTree } from './abstractSyntaxTree'
import { initPromise } from './rust' import { initPromise } from './rust'
beforeAll(() => initPromise) beforeAll(() => initPromise)

View File

@ -7,16 +7,15 @@ import {
VariableDeclarator, VariableDeclarator,
ExpressionStatement, ExpressionStatement,
Value, Value,
getNodeFromPath,
Literal, Literal,
PipeSubstitution, PipeSubstitution,
Identifier, Identifier,
ArrayExpression, ArrayExpression,
ObjectExpression, ObjectExpression,
getNodePathFromSourceRange,
UnaryExpression, UnaryExpression,
BinaryExpression, BinaryExpression,
} from './abstractSyntaxTree' } from './abstractSyntaxTree'
import { getNodeFromPath, getNodePathFromSourceRange } from './queryAst'
import { PathToNode, ProgramMemory } from './executor' import { PathToNode, ProgramMemory } from './executor'
import { import {
addTagForSketchOnFace, addTagForSketchOnFace,

135
src/lang/queryAst.ts Normal file
View File

@ -0,0 +1,135 @@
import { PathToNode } from './executor'
import { Range } from '../useStore'
import { Program } from './abstractSyntaxTree'
export function getNodeFromPath<T>(
node: Program,
path: (string | number)[],
stopAt: string = '',
returnEarly = false
): {
node: T
path: PathToNode
} {
let currentNode = node as any
let stopAtNode = null
let successfulPaths: PathToNode = []
let pathsExplored: PathToNode = []
for (const pathItem of path) {
try {
if (typeof currentNode[pathItem] !== 'object')
throw new Error('not an object')
currentNode = currentNode[pathItem]
successfulPaths.push(pathItem)
if (!stopAtNode) {
pathsExplored.push(pathItem)
}
if (currentNode.type === stopAt) {
// it will match the deepest node of the type
// instead of returning at the first match
stopAtNode = currentNode
if (returnEarly) {
return {
node: stopAtNode,
path: pathsExplored,
}
}
}
} catch (e) {
console.error(
`Could not find path ${pathItem} in node ${JSON.stringify(
currentNode,
null,
2
)}, successful path was ${successfulPaths}`
)
}
}
return {
node: stopAtNode || currentNode,
path: pathsExplored,
}
}
export function getNodeFromPathCurry(
node: Program,
path: (string | number)[]
): <T>(
stopAt: string,
returnEarly?: boolean
) => {
node: T
path: PathToNode
} {
return <T>(stopAt: string = '', returnEarly = false) => {
return getNodeFromPath<T>(node, path, stopAt, returnEarly)
}
}
export function getNodePathFromSourceRange(
node: Program,
sourceRange: Range,
previousPath: PathToNode = []
): PathToNode {
const [start, end] = sourceRange
let path: PathToNode = [...previousPath, 'body']
const _node = { ...node }
// loop over each statement in body getting the index with a for loop
for (
let statementIndex = 0;
statementIndex < _node.body.length;
statementIndex++
) {
const statement = _node.body[statementIndex]
if (statement.start <= start && statement.end >= end) {
path.push(statementIndex)
if (statement.type === 'ExpressionStatement') {
const expression = statement.expression
if (expression.start <= start && expression.end >= end) {
path.push('expression')
if (expression.type === 'CallExpression') {
const callee = expression.callee
if (callee.start <= start && callee.end >= end) {
path.push('callee')
if (callee.type === 'Identifier') {
}
}
}
}
} else if (statement.type === 'VariableDeclaration') {
const declarations = statement.declarations
for (let decIndex = 0; decIndex < declarations.length; decIndex++) {
const declaration = declarations[decIndex]
if (declaration.start <= start && declaration.end >= end) {
path.push('declarations')
path.push(decIndex)
const init = declaration.init
if (init.start <= start && init.end >= end) {
path.push('init')
if (init.type === 'PipeExpression') {
const body = init.body
for (let pipeIndex = 0; pipeIndex < body.length; pipeIndex++) {
const pipe = body[pipeIndex]
if (pipe.start <= start && pipe.end >= end) {
path.push('body')
path.push(pipeIndex)
}
}
} else if (init.type === 'CallExpression') {
const callee = init.callee
if (callee.start <= start && callee.end >= end) {
path.push('callee')
if (callee.type === 'Identifier') {
}
}
}
}
}
}
}
}
}
return path
}

View File

@ -1,4 +1,3 @@
import { start } from 'repl'
import { import {
Program, Program,
BinaryExpression, BinaryExpression,

View File

@ -6,10 +6,8 @@ import {
getXComponent, getXComponent,
} from './sketch' } from './sketch'
import { lexer } from '../tokeniser' import { lexer } from '../tokeniser'
import { import { abstractSyntaxTree } from '../abstractSyntaxTree'
abstractSyntaxTree, import { getNodePathFromSourceRange } from '../queryAst'
getNodePathFromSourceRange,
} from '../abstractSyntaxTree'
import { recast } from '../recast' import { recast } from '../recast'
import { executor } from '../executor' import { executor } from '../executor'
import { initPromise } from '../rust' import { initPromise } from '../rust'

View File

@ -10,12 +10,14 @@ import {
PipeExpression, PipeExpression,
CallExpression, CallExpression,
VariableDeclarator, VariableDeclarator,
getNodeFromPath,
getNodeFromPathCurry,
getNodePathFromSourceRange,
Value, Value,
Literal, Literal,
} from '../abstractSyntaxTree' } from '../abstractSyntaxTree'
import {
getNodeFromPath,
getNodeFromPathCurry,
getNodePathFromSourceRange,
} from '../queryAst'
import { lineGeo } from '../engine' import { lineGeo } from '../engine'
import { GuiModes, toolTips, TooTip } from '../../useStore' import { GuiModes, toolTips, TooTip } from '../../useStore'
import { getLastIndex } from '../modifyAst' import { getLastIndex } from '../modifyAst'
@ -24,7 +26,6 @@ import {
SketchLineHelper, SketchLineHelper,
ModifyAstBase, ModifyAstBase,
InternalFn, InternalFn,
SketchCallTransfromMap,
TransformCallback, TransformCallback,
} from './stdTypes' } from './stdTypes'
@ -55,17 +56,6 @@ export function getCoordsFromPaths(skGroup: SketchGroup, index = 0): Coords2d {
return [0, 0] return [0, 0]
} }
function createCallWrapper(
a: TooTip,
val: [Value, Value] | Value,
tag?: Value
) {
return createCallExpression(a, [
createFirstArg(a, val, tag),
createPipeSubstitution(),
])
}
export function createFirstArg( export function createFirstArg(
sketchFn: TooTip, sketchFn: TooTip,
val: Value | [Value, Value], val: Value | [Value, Value],
@ -97,34 +87,6 @@ export function createFirstArg(
throw new Error('all sketch line types should have been covered') throw new Error('all sketch line types should have been covered')
} }
function tranformerDefaults(
filterOut: TooTip[] = [],
tag?: Value
): Partial<SketchCallTransfromMap> {
const All: SketchCallTransfromMap = {
line: (args) => createCallWrapper('line', args, tag),
lineTo: (args) => createCallWrapper('lineTo', args, tag),
angledLine: (args) => createCallWrapper('angledLine', args, tag),
angledLineOfXLength: (args) =>
createCallWrapper('angledLineOfXLength', args, tag),
angledLineOfYLength: (args) =>
createCallWrapper('angledLineOfYLength', args, tag),
angledLineToX: (args) => createCallWrapper('angledLineToX', args, tag),
angledLineToY: (args) => createCallWrapper('angledLineToY', args, tag),
xLine: (args) => createCallWrapper('xLine', args[0], tag),
xLineTo: (args) => createCallWrapper('xLineTo', args[0], tag),
yLine: (args) => createCallWrapper('yLine', args[1], tag),
yLineTo: (args) => createCallWrapper('yLineTo', args[1], tag),
}
const result: Partial<SketchCallTransfromMap> = {}
toolTips.forEach((key) => {
if (!filterOut.includes(key)) {
result[key] = All[key]
}
})
return result
}
export const lineTo: SketchLineHelper = { export const lineTo: SketchLineHelper = {
fn: ( fn: (
{ sourceRange, programMemory }, { sourceRange, programMemory },
@ -567,7 +529,6 @@ export const angledLine: SketchLineHelper = {
| { | {
angle: number angle: number
length: number length: number
// name?: string
tag?: string tag?: string
}, },
previousSketch: SketchGroup previousSketch: SketchGroup
@ -671,7 +632,6 @@ export const angledLineOfXLength: SketchLineHelper = {
| { | {
angle: number angle: number
length: number length: number
// name?: string
tag?: string tag?: string
}, },
previousSketch: SketchGroup previousSketch: SketchGroup
@ -881,15 +841,7 @@ export const angledLineToX: SketchLineHelper = {
previousSketch previousSketch
) )
}, },
add: ({ add: ({ node, pathToNode, to, from, createCallback, replaceExisting }) => {
node,
pathToNode,
to,
from,
createCallback,
replaceExisting,
// from: [number, number],
}) => {
const _node = { ...node } const _node = { ...node }
const { node: pipe } = getNodeFromPath<PipeExpression>( const { node: pipe } = getNodeFromPath<PipeExpression>(
_node, _node,
@ -926,9 +878,6 @@ export const angledLineToX: SketchLineHelper = {
const xLength = roundOff(to[0], 2) const xLength = roundOff(to[0], 2)
const firstArg = callExpression.arguments?.[0] const firstArg = callExpression.arguments?.[0]
// const adjustedXLength = isAngleLiteral(firstArg)
// ? Math.abs(xLength)
// : xLength // todo make work for variable angle > 180
const adjustedXLength = xLength const adjustedXLength = xLength
const angleLit = createLiteral(angle) const angleLit = createLiteral(angle)
@ -974,15 +923,7 @@ export const angledLineToY: SketchLineHelper = {
previousSketch previousSketch
) )
}, },
add: ({ add: ({ node, pathToNode, to, from, createCallback, replaceExisting }) => {
node,
previousProgramMemory,
pathToNode,
to,
from,
createCallback,
replaceExisting,
}) => {
const _node = { ...node } const _node = { ...node }
const { node: pipe } = getNodeFromPath<PipeExpression>( const { node: pipe } = getNodeFromPath<PipeExpression>(
_node, _node,
@ -1019,9 +960,6 @@ export const angledLineToY: SketchLineHelper = {
const xLength = roundOff(to[1], 2) const xLength = roundOff(to[1], 2)
const firstArg = callExpression.arguments?.[0] const firstArg = callExpression.arguments?.[0]
// const adjustedXLength = isAngleLiteral(firstArg)
// ? Math.abs(xLength)
// : xLength // todo make work for variable angle > 180
const adjustedXLength = xLength const adjustedXLength = xLength
const angleLit = createLiteral(angle) const angleLit = createLiteral(angle)

View File

@ -3,17 +3,18 @@ import { Range, Ranges, toolTips, TooTip } from '../../useStore'
import { import {
BinaryPart, BinaryPart,
CallExpression, CallExpression,
getNodeFromPath,
getNodeFromPathCurry,
getNodePathFromSourceRange,
Program, Program,
Value, Value,
VariableDeclarator, VariableDeclarator,
} from '../abstractSyntaxTree' } from '../abstractSyntaxTree'
import {
getNodeFromPath,
getNodeFromPathCurry,
getNodePathFromSourceRange,
} from '../queryAst'
import { import {
createBinaryExpression, createBinaryExpression,
createCallExpression, createCallExpression,
createIdentifier,
createLiteral, createLiteral,
createPipeSubstitution, createPipeSubstitution,
createUnaryExpression, createUnaryExpression,

View File

@ -78,7 +78,9 @@ const translate: InternalFn = <T extends SketchGroup | ExtrudeGroup>(
const min: InternalFn = (_, a: number, b: number): number => Math.min(a, b) const min: InternalFn = (_, a: number, b: number): number => Math.min(a, b)
const legLen: InternalFn = (_, hypotenuse: number, leg: number): number => const legLen: InternalFn = (_, hypotenuse: number, leg: number): number =>
Math.sqrt(hypotenuse ** 2 - Math.min(Math.abs(leg), Math.abs(hypotenuse)) ** 2) Math.sqrt(
hypotenuse ** 2 - Math.min(Math.abs(leg), Math.abs(hypotenuse)) ** 2
)
const legAngX: InternalFn = (_, hypotenuse: number, leg: number): number => const legAngX: InternalFn = (_, hypotenuse: number, leg: number): number =>
(Math.acos(Math.min(leg, hypotenuse) / hypotenuse) * 180) / Math.PI (Math.acos(Math.min(leg, hypotenuse) / hypotenuse) * 180) / Math.PI

View File

@ -1,11 +1,8 @@
import create from 'zustand' import create from 'zustand'
import { persist } from 'zustand/middleware' import { persist } from 'zustand/middleware'
import { addLineHighlight, EditorView } from './editor/highlightextension' import { addLineHighlight, EditorView } from './editor/highlightextension'
import { import { Program, abstractSyntaxTree } from './lang/abstractSyntaxTree'
Program, import { getNodeFromPath } from './lang/queryAst'
abstractSyntaxTree,
getNodeFromPath,
} from './lang/abstractSyntaxTree'
import { ProgramMemory, Position, PathToNode, Rotation } from './lang/executor' import { ProgramMemory, Position, PathToNode, Rotation } from './lang/executor'
import { recast } from './lang/recast' import { recast } from './lang/recast'
import { asyncLexer } from './lang/tokeniser' import { asyncLexer } from './lang/tokeniser'