Skip to content

Commit

Permalink
Merge pull request #37 from rycont/rollback-function-invoke-syntax
Browse files Browse the repository at this point in the history
Rollback function invoke syntax
  • Loading branch information
rycont authored Nov 9, 2024
2 parents cf077a7 + 9618ecf commit d26ebea
Show file tree
Hide file tree
Showing 14 changed files with 121 additions and 51 deletions.
4 changes: 2 additions & 2 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"@vue/runtime-dom": "npm:@vue/runtime-dom@^3.5.12",
"@vueuse/core": "npm:@vueuse/core@^11.2.0",
"ansi-to-html": "npm:ansi-to-html@^0.7.2",
"assert": "https://deno.land/[email protected]/assert/mod.ts",
"assert": "jsr:@std/assert",
"quickjs-emscripten": "npm:quickjs-emscripten@^0.31.0",
"quickjs-emscripten-core": "npm:quickjs-emscripten-core@^0.31.0",
"typedoc": "npm:[email protected]",
Expand Down Expand Up @@ -34,7 +34,7 @@
}
},
"name": "@yaksok-ts/core",
"version": "0.1.12",
"version": "0.1.13",
"exports": "./src/index.ts",
"nodeModulesDir": "auto"
}
12 changes: 12 additions & 0 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 14 additions & 23 deletions runtest.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,22 @@
import { QuickJS, yaksok } from './src/index.ts'

const quickJS = new QuickJS({
prompt: () => {
return '10'
},
})

await quickJS.init()
import { yaksok } from './src/index.ts'

yaksok(
`
번역(QuickJS), 에러 발생
***
return ("ㅁㄴㅇㄹ" as string) */ 10
***
약속, (음식)을/를 (사람)와/과 먹기
"맛있는 " + 음식 + ", " + 사람 + "의 입으로 모두 들어갑니다." 보여주기
에러 발생
`,
{
runFFI(_, code, args) {
const result = quickJS.run(code, args)

if (!result) {
throw new Error('Result is null')
}
"피자"를 "철수"와 먹기
"햄버거"를 "영희"와 먹기
"치킨"을 "형님"과 먹기
"초밥"을 "동생"과 먹기
return result
("피자")를 ("철수")와 먹기
("햄버거")를 ("영희")와 먹기
("치킨")을 ("형님")과 먹기
("초밥")을 ("동생")과 먹기`,
{
flags: {
'future-function-invoke-syntax': false,
},
},
)
5 changes: 5 additions & 0 deletions src/contant/feature-flags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum FEATURE_FLAG {
FUTURE_FUNCTION_INVOKE_SYNTAX = 'future-function-invoke-syntax',
}

export type EnabledFlags = Partial<Record<FEATURE_FLAG, boolean>>
5 changes: 5 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ import { run } from '../src/runtime/run.ts'
import { parse } from './prepare/parse/index.ts'
import { tokenize } from './prepare/tokenize/index.ts'
import { ErrorInModuleError } from './error/mention.ts'
import { EnabledFlags } from './contant/feature-flags.ts'

interface YaksokConfig {
stdout: (message: string) => void
stderr: (message: string) => void
entryPoint: string
runFFI: (runtime: string, code: string, args: Params) => ValueTypes
flags: EnabledFlags
}

const defaultConfig: YaksokConfig = {
Expand All @@ -30,6 +32,7 @@ const defaultConfig: YaksokConfig = {
runFFI: (runtime: string) => {
throw new Error(`FFI ${runtime} not implemented`)
},
flags: {},
}

export class CodeRunner {
Expand Down Expand Up @@ -114,6 +117,7 @@ export class Yaksok implements YaksokConfig {
stderr: YaksokConfig['stderr']
entryPoint: YaksokConfig['entryPoint']
runFFI: YaksokConfig['runFFI']
flags: Partial<EnabledFlags> = {}

runners: Record<string, CodeRunner> = {}
ran: Record<string, boolean> = {}
Expand All @@ -126,6 +130,7 @@ export class Yaksok implements YaksokConfig {
this.stderr = config.stderr || defaultConfig.stderr
this.entryPoint = config.entryPoint || defaultConfig.entryPoint
this.runFFI = config.runFFI || defaultConfig.runFFI
this.flags = config.flags || defaultConfig.flags
}

getRunner(fileName = this.entryPoint): CodeRunner {
Expand Down
2 changes: 1 addition & 1 deletion src/prepare/parse/dynamicRule/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { TokenizeResult } from '../../tokenize/index.ts'
import type { Yaksok } from '../../../index.ts'

export function createDynamicRule(tokenized: TokenizeResult, runtime: Yaksok) {
const localRules = createLocalDynamicRules(tokenized)
const localRules = createLocalDynamicRules(tokenized, runtime)
const mentioningRules = getDynamicRulesFromMention(
tokenized.tokens,
runtime,
Expand Down
45 changes: 35 additions & 10 deletions src/prepare/parse/dynamicRule/local/createRuleFromFunctionHeader.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import {
EnabledFlags,
FEATURE_FLAG,
} from '../../../../contant/feature-flags.ts'
import { Evaluable } from '../../../../node/base.ts'
import { ValueWithParenthesis } from '../../../../node/calculation.ts'
import { type Node, Identifier, Expression } from '../../../../node/index.ts'
import { isParentheses } from '../../../../util/isBracket.ts'
import { createFunctionDeclareRule } from './declareRule.ts'
Expand All @@ -8,19 +14,38 @@ import type {
import { getVariants } from './getVariants.ts'
import { createFunctionInvokeRule } from './invokeRule.ts'

export function createRuleFromFunctionHeader(
subtokens: Node[],
type: keyof typeof functionRuleByType,
) {
assertValidFunctionHeader(subtokens)
interface Args {
subtokens: Node[]
type: keyof typeof functionRuleByType
flags: EnabledFlags
}

const name = getFunctionNameFromHeader(subtokens)
const variants = [...getVariants(subtokens)]
export function createRuleFromFunctionHeader(args: Args) {
assertValidFunctionHeader(args.subtokens)

const declareRule = createFunctionDeclareRule(name, subtokens, {
type,
const name = getFunctionNameFromHeader(args.subtokens)
const variants = [...getVariants(args.subtokens)]

const declareRule = createFunctionDeclareRule(name, args.subtokens, {
type: args.type,
})
const invokeRules = variants.map((v) => createFunctionInvokeRule(name, v))

let invokeRules = variants.map((v) => createFunctionInvokeRule(name, v))

if (!args.flags[FEATURE_FLAG.FUTURE_FUNCTION_INVOKE_SYNTAX]) {
invokeRules = invokeRules.map((rule) => ({
...rule,
pattern: rule.pattern.map((unit) => {
if (unit.type === ValueWithParenthesis) {
return {
type: Evaluable,
}
}

return unit
}),
}))
}

return [declareRule, ...invokeRules]
}
Expand Down
21 changes: 15 additions & 6 deletions src/prepare/parse/dynamicRule/local/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import type { TokenizeResult } from '../../../tokenize/index.ts'
import type { Yaksok } from '../../../../index.ts'
import { createRuleFromFunctionHeader } from './createRuleFromFunctionHeader.ts'

export function createLocalDynamicRules({
functionHeaders,
ffiHeaders,
}: TokenizeResult) {
export function createLocalDynamicRules(
{ functionHeaders, ffiHeaders }: TokenizeResult,
runtime: Yaksok,
) {
const functionRules = functionHeaders.flatMap((rule) =>
createRuleFromFunctionHeader(rule, 'yaksok'),
createRuleFromFunctionHeader({
subtokens: rule,
type: 'yaksok',
flags: runtime.flags,
}),
)

const ffiRules = ffiHeaders.flatMap((header) =>
createRuleFromFunctionHeader(header, 'ffi'),
createRuleFromFunctionHeader({
subtokens: header,
type: 'ffi',
flags: runtime.flags,
}),
)

return [...functionRules, ...ffiRules].map((e) => [e])
Expand Down
2 changes: 1 addition & 1 deletion test/codes/bmi.yak
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
약속, 키 (키) 몸무게 (몸무게)의 비만도
결과: 몸무게 / (키 / 100 * 키 / 100)

비만도: 키 (177) 몸무게 (68)의 비만도
비만도: 키 177 몸무게 68 의 비만도
비만도 보여주기
8 changes: 4 additions & 4 deletions test/codes/function-variants.yak
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
약속, (음식)을/를 (사람)와/과 먹기
"맛있는 " + 음식 + ", " + 사람 + "의 입으로 모두 들어갑니다." 보여주기

("피자")를 ("철수")와 먹기
("햄버거")를 ("영희")와 먹기
("치킨")을 ("형님")과 먹기
("초밥")을 ("동생")과 먹기
"피자""철수"와 먹기
"햄버거""영희"와 먹기
"치킨""형님"과 먹기
"초밥""동생"과 먹기
2 changes: 1 addition & 1 deletion test/codes/hanoi.yak
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
막대1 + " -> " + 막대3 보여주기
하노이 (개수-1) (막대2) (막대1) (막대3) 이동

하노이 (3) ("A") ("B") ("C") 이동
하노이 3 "A" "B" "C" 이동
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { assertIsError, unreachable } from 'assert'
import { yaksok } from '../../src/index.ts'
import { UnexpectedTokenError } from '../../src/error/index.ts'

Deno.test('인자를 닫는 괄호가 필요하지만 없습니다', () => {
Deno.test('인자를 닫는 괄호가 제 위치에 없습니다', () => {
try {
yaksok(`
약속, (음식 10)을 맛있게 만들기
Expand Down
23 changes: 23 additions & 0 deletions test/future-function-invoke-syntax.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { equal } from 'assert'
import { yaksok } from '../src/index.ts'

Deno.test('미래의 약속 호출 문법', () => {
let output = ''

yaksok(
`약속, (A)와 (B)를 더하기
결과: A + B
(4)와 (5)를 더하기 보여주기`,
{
flags: {
'future-function-invoke-syntax': true,
},
stdout(value) {
output += value + '\n'
},
},
)

equal(output, '9\n')
})
4 changes: 2 additions & 2 deletions test/mention.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ Deno.test('Mentioning', () => {
`.trim(),
main: `
"청량리부터 안동까지 KTX 이음을 타면" 보여주기
(@코레일 (@차종 KTX이음)으로 (@역간거리 ("청량리")부터 ("안동")까지)km을 이동할 때 운임) + "원" 보여주기
(@코레일 (@차종 KTX이음)으로 (@역간거리 "청량리" 부터 "안동" 까지)km을 이동할 때 운임) + "원" 보여주기
"판교부터 충주까지 무궁화호를 타면" 보여주기
(@코레일 (@차종 무궁화호)으로 (@역간거리 ("판교")부터 ("충주")까지)km을 이동할 때 운임) + "원" 보여주기
(@코레일 (@차종 무궁화호)으로 (@역간거리 "판교" 부터 "충주" 까지)km을 이동할 때 운임) + "원" 보여주기
@코레일 출발하기
`,
Expand Down

0 comments on commit d26ebea

Please sign in to comment.