Skip to content

Commit

Permalink
fix: figure function parameters with explicit retriever
Browse files Browse the repository at this point in the history
  • Loading branch information
rycont committed Nov 14, 2024
1 parent 81d9a12 commit 948d4cb
Showing 2 changed files with 92 additions and 47 deletions.
65 changes: 31 additions & 34 deletions runtest.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,38 @@
import { FunctionParams } from './src/mod.ts'
import { NumberValue } from './src/mod.ts'
import { yaksok } from './src/mod.ts'

yaksok(
`
번역(JavaScript), (A)와 (B) 사이 랜덤 수
***
return Math.floor(Math.random() * (B - A) + A)
***
약속, 회전설정 (회전)
결과: "rotate:" + 회전
(1)와 (10) 사이 랜덤 수 보여주기
`,
{
runFFI: (runtime, code, params) => {
if (runtime !== 'JavaScript') {
throw new Error('지원하지 않는 런타임입니다')
}

const runnableCode = buildCodeFromCodeAndParams(code, params)
const resultInJS = eval(runnableCode)

if (typeof resultInJS !== 'number') {
throw new Error('결과값은 숫자여야 합니다')
}

return new NumberValue(resultInJS)
},
},
)
약속, 시간설정 (시간)
결과: "time:" + 시간
약속, (A) 합 (B)
결과: A + "<join>" + B
약속, (각도)도 회전하기
회전설정 각도 보여주기
약속, (시간)초 동안 (각도)도 회전하기
(시간설정 시간) 합 (회전설정 각도) 보여주기
function buildCodeFromCodeAndParams(code: string, params: FunctionParams) {
const paramNames = Object.keys(params)
const paramsInJS = Object.fromEntries(
Object.entries(params).map(([key, value]) => [key, value.value]),
)
각도: 45
시간: 30
return `((${paramNames.join(', ')}) => {${code}})(${Object.values(
paramsInJS,
).join(', ')})`
}
(3)초 동안 (90)도 회전하기
3 초 동안 90 도 회전하기
(3)초 동안 90 도 회전하기
3 초 동안 (90)도 회전하기
시간 초 동안 각도 도 회전하기
(시간)초 동안 (각도)도 회전하기
(시간)초 동안 각도 도 회전하기
시간 초 동안 (각도)도 회전하기
(90)도 회전하기
90 도 회전하기
각도 도 회전하기
(각도)도 회전하기
`,
)
74 changes: 61 additions & 13 deletions src/prepare/parse/dynamicRule/local/invokeRule.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { FunctionParams } from '../../../../constant/type.ts'
import {
type Node,
Expression,
@@ -19,10 +20,13 @@ export function createFunctionInvokeRule(
.map(functionHeaderToInvokeMap)
.filter(Boolean) as PatternUnit[]

const paramNameIndexMap = getParamNameIndexMapFromHeader(subtokens)

return {
pattern: invokeTemplate,
factory(nodes: Node[]) {
const params = getParamsFromMatchedNodes(subtokens, nodes)
const params = getParamsFromMatchedNodes(paramNameIndexMap, nodes)

return new FunctionInvoke({
name,
params,
@@ -35,20 +39,64 @@ export function createFunctionInvokeRule(
}

function getParamsFromMatchedNodes(
template: FunctionHeaderNode[],
matchedNodes: Node[],
paramNameIndexMap: Map<string, number>,
nodes: Node[],
) {
const params = {} as FunctionParams

for (const [paramName, index] of paramNameIndexMap) {
const node = nodes[index]

if (!(node instanceof Evaluable)) {
throw new Error('Node is not Evaluable')
}

params[paramName] = node
}

return params
}

function getParamNameIndexMapFromHeader(
functionHeaderNodes: FunctionHeaderNode[],
) {
return Object.fromEntries(
template
.filter((token) => !(token instanceof Expression))
.map((token, i) => [token, matchedNodes[i]])
.filter(
(set): set is [Identifier, Evaluable] =>
set[1] instanceof Evaluable &&
!(set[1] instanceof Identifier),
)
.map(([token, node]) => [token.value, node]),
let parenthesesCount = 0

const paramNameIndexMap = new Map(
(
functionHeaderNodes
.map((token, index) => {
if (token instanceof Expression) {
parenthesesCount += 1
return null
}

const prevToken = functionHeaderNodes[index - 1]
const nextToken = functionHeaderNodes[index + 1]

if (!prevToken || !nextToken) {
return null
}

const isPreviousTokenOpeningParentheses =
isParentheses(prevToken) === BRACKET_TYPE.OPENING
const isNextTokenClosingParentheses =
isParentheses(nextToken) === BRACKET_TYPE.CLOSING

if (
!isPreviousTokenOpeningParentheses ||
!isNextTokenClosingParentheses
) {
return null
}

return [token, index - parenthesesCount]
})
.filter(Boolean) as [FunctionHeaderNode, number][]
).map(([token, index]) => [token.value, index]),
)

return paramNameIndexMap
}

function functionHeaderToInvokeMap(

0 comments on commit 948d4cb

Please sign in to comment.