Skip to content

Commit

Permalink
Use Set for better performance
Browse files Browse the repository at this point in the history
  • Loading branch information
graphemecluster committed Oct 7, 2024
1 parent e5e1066 commit 8437a0d
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 99 deletions.
24 changes: 12 additions & 12 deletions src/lib/壓縮表示.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ const 韻序表 = [
*/
export function encode音韻編碼(地位: 音韻地位): string {
const {,,,,,} = 地位;
const 母序 = 所有..indexOf();
const 母序 = [...所有.].indexOf();
const 韻序 = 韻序表.indexOf() + +([...'東歌麻庚'].includes() && !['一', '二'].includes());

// NOTE the value `-1` is expected when the argument is `null`
const 呼序 = 所有..indexOf(!) + 1;
const 類序 = 所有..indexOf(!) + 1;
const 呼序 = [...所有.].indexOf(!) + 1;
const 類序 = [...所有.].indexOf(!) + 1;

const 呼類聲序 = (呼序 << 4) | (類序 << 2) | 所有..indexOf();
const 呼類聲序 = (呼序 << 4) | (類序 << 2) | [...所有.].indexOf();

return 編碼表[母序] + 編碼表[韻序] + 編碼表[呼類聲序];
}
Expand All @@ -55,8 +55,8 @@ export function decode音韻編碼(編碼: string): 音韻地位 {
assert(index !== -1, () => `Invalid character in 編碼: ${JSON.stringify(ch)}`);
return index;
});
assert(母序 < 所有..length, () => `Invalid 母序號: ${母序}`);
const = 所有.[母序];
assert(母序 < [...所有.].length, () => `Invalid 母序號: ${母序}`);
const = [...所有.][母序];

assert(韻序 < 韻序表.length, () => `Invalid 韻序號: ${韻序}`);
let = 韻序表[韻序];
Expand All @@ -65,7 +65,7 @@ export function decode音韻編碼(編碼: string): 音韻地位 {
}
let : string;
for (const [韻等, 各韻] of Object.entries(等韻搭配)) {
if (各韻.includes()) {
if (各韻.has()) {
= 韻等[+(韻序表[韻序] === '*')];
if ( === '三' && [...'端透定泥'].includes()) {
= '四';
Expand All @@ -75,15 +75,15 @@ export function decode音韻編碼(編碼: string): 音韻地位 {
}

const 呼序 = 呼類聲序 >> 4;
assert(呼序 <= 所有..length, () => `Invalid 呼序號: ${呼序}`);
const = 呼序 ? 所有.[呼序 - 1] : null;
assert(呼序 <= [...所有.].length, () => `Invalid 呼序號: ${呼序}`);
const = 呼序 ? [...所有.][呼序 - 1] : null;

const 類序 = (呼類聲序 >> 2) & 0b11;
assert(類序 <= 所有..length, () => `Invalid 類序號: ${類序}`);
const = 類序 ? 所有.[類序 - 1] : null;
assert(類序 <= [...所有.].length, () => `Invalid 類序號: ${類序}`);
const = 類序 ? [...所有.][類序 - 1] : null;

const 聲序 = 呼類聲序 & 0b11;
const = 所有.[聲序];
const = [...所有.][聲序];

// NOTE type assertion safe because the constructor checks it
return new 音韻地位(, , !, , , , _UNCHECKED);
Expand Down
20 changes: 10 additions & 10 deletions src/lib/常用表達式.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,31 @@
import { 呼韻搭配, 等韻搭配 } from './音韻屬性常量';

/** 一等韻 */
export const 一等韻 = 等韻搭配..join('') + '韻';
export const 一等韻 = [...等韻搭配.].join('') + '韻';
/** 二等韻 */
export const 二等韻 = 等韻搭配..join('') + '韻';
export const 二等韻 = [...等韻搭配.].join('') + '韻';
/** 三等韻(注意:拼端組時為四等) */
export const 三等韻 = 等韻搭配..join('') + '韻';
export const 三等韻 = [...等韻搭配.].join('') + '韻';
/** 四等韻 */
export const 四等韻 = 等韻搭配..join('') + '韻';
export const 四等韻 = [...等韻搭配.].join('') + '韻';
/** 一三等韻 */
export const 一三等韻 = 等韻搭配.一三.join('') + '韻';
export const 一三等韻 = [...等韻搭配.一三].join('') + '韻';
/** 二三等韻(注意:拼端組時為二四等) */
export const 二三等韻 = 等韻搭配.二三.join('') + '韻';
export const 二三等韻 = [...等韻搭配.二三].join('') + '韻';

/**
* 韻內分開合口的韻
*/
export const 分開合韻 = 呼韻搭配.開合.join('') + '韻';
export const 分開合韻 = [...呼韻搭配.開合].join('') + '韻';
/**
* 僅為開口的韻(含之、魚韻及效、深、咸攝諸韻)
*/
export const 開口韻 = 呼韻搭配..join('') + '韻';
export const 開口韻 = [...呼韻搭配.].join('') + '韻';
/**
* 僅為合口的韻
*/
export const 合口韻 = 呼韻搭配..join('') + '韻';
export const 合口韻 = [...呼韻搭配.].join('') + '韻';
/**
* 開合中立韻(東冬鍾江模尤侯)
*/
export const 開合中立韻 = 呼韻搭配.中立.join('') + '韻';
export const 開合中立韻 = [...呼韻搭配.中立].join('') + '韻';
103 changes: 49 additions & 54 deletions src/lib/音韻地位.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ import { 母到清濁, 母到組, 母到音, 韻到攝 } from './拓展音韻屬
import { 呼韻搭配, 所有, 等母搭配, 等韻搭配, 鈍音母, 陰聲韻 } from './音韻屬性常量';

const pattern描述 = new RegExp(
`^([${所有..join('')}])([${所有..join('')}]?)([${所有..join('')}]?)` +
`([${所有..join('')}]?)([${所有..join('')}])([${所有..join('')}])$`,
`^([${[...所有.].join('')}])([${[...所有.].join('')}]?)([${[...所有.].join('')}]?)` +
`([${[...所有.].join('')}]?)([${[...所有.].join('')}])([${[...所有.].join('')}])$`,
'u',
);

// for 音韻地位.屬於
const 表達式屬性可取值 = {
...所有,
: [...'脣舌齒牙喉'] as const,
: [...'通江止遇蟹臻山效果假宕梗曾流深咸'] as const,
: [...'幫端知精莊章見影'] as const,
: new Set('脣舌齒牙喉'),
: new Set('通江止遇蟹臻山效果假宕梗曾流深咸'),
: new Set('幫端知精莊章見影'),
};
const 鈍音組 = [...'幫見影'] as const;
const 鈍音組 = new Set('幫見影');

/**
* @see {@link 音韻地位.判斷}
Expand Down Expand Up @@ -311,7 +311,7 @@ export class 音韻地位 {
*/
get 韻別(): string {
const {,} = this;
return 陰聲韻.includes() ? '陰' : === '入' ? '入' : '陽';
return 陰聲韻.has() ? '陰' : === '入' ? '入' : '陽';
}

/**
Expand Down Expand Up @@ -376,12 +376,12 @@ export class 音韻地位 {
}
if ( === '合' && === '云') {
= null;
} else if ( && 呼韻搭配[ as '開' | '合'].includes()) {
} else if ( && 呼韻搭配[ as '開' | '合'].has()) {
= null;
}
if ( === '三' && [...'羣邪俟'].includes()) {
if ( === '三' && new Set('羣邪俟').has()) {
= '';
} else if (等母搭配..includes() || ![...等韻搭配.一三, ...等韻搭配.二三].includes()) {
} else if (等母搭配..has() || ![...等韻搭配.一三, ...等韻搭配.二三].includes()) {
= '';
}
return + ( ?? '') + + ( ?? '') + + ;
Expand Down Expand Up @@ -451,9 +451,9 @@ export class 音韻地位 {
*/
get 韻圖等(): string {
const {,,} = this;
if ([...'莊初崇生俟'].includes()) {
if (new Set('莊初崇生俟').has()) {
return '二';
} else if ( === 'A' || ( === '三' && [...'精清從心邪以'].includes())) {
} else if ( === 'A' || ( === '三' && new Set('精清從心邪以').has())) {
return '四';
} else {
return ;
Expand Down Expand Up @@ -609,13 +609,13 @@ export class 音韻地位 {
if (/^不分類$/.exec(token)) return === null;
if ((match = /^(清|濁)音$/.exec(token))) return 清濁[1] === match[1];
if ((match = /^[全次][清濁]$/.exec(token))) return 清濁 === match[0];
if (/^鈍音$/.exec(token)) return 鈍音組.includes(!);
if (/^銳音$/.exec(token)) return !鈍音組.includes(!);
if (/^鈍音$/.exec(token)) return 鈍音組.has(!);
if (/^銳音$/.exec(token)) return !鈍音組.has(!);
if ((match = /^(.+?)([母等類韻音攝組聲])$/.exec(token))) {
const values = [...match[1]];
const key = match[2] as keyof typeof 表達式屬性可取值;
const possibleValues = 表達式屬性可取值[key];
const invalidValues = values.filter(i => !possibleValues.includes(i));
const invalidValues = values.filter(i => !possibleValues.has(i));
if (invalidValues.length) {
throw new Error(`unknown ${key}: ${invalidValues.join(', ')}`);
}
Expand Down Expand Up @@ -799,8 +799,8 @@ export class 音韻地位 {
* > 音韻地位 = TshetUinh.音韻地位.from描述('幫三C凡入');
* > 音韻地位.判斷([
* > ['遇果假攝 或 支脂之佳韻', ''],
* > ['蟹攝 或 微韻', 'i'],
* > ['效流攝', 'u'],
* > ['蟹攝 或 微韻', 'j'],
* > ['效流攝', 'w'],
* > ['深咸攝', [
* > ['舒聲', 'm'],
* > ['入聲', 'p']
Expand Down Expand Up @@ -959,7 +959,7 @@ export class 音韻地位 {
['韻', ],
['聲', ],
] as const) {
if (!(( === null && !!nullable) || 所有[屬性].includes(!))) {
if (!(( === null && !!nullable) || 所有[屬性].has(!))) {
const suggestion = (
{
: { : '孃', : '羣' },
Expand All @@ -974,36 +974,36 @@ export class 音韻地位 {
// 順序:從搭配規則從基本到精細

// 聲(僅韻-聲搭配)
=== '入' && 陰聲韻.includes() && reject(`unexpected ${}韻入聲`);
=== '入' && 陰聲韻.has() && reject(`unexpected ${}韻入聲`);

// 等、呼、類(基本)
// 母-等
for (const [搭配等, 搭配母] of Object.entries(等母搭配)) {
if (搭配母.includes()) {
if (搭配母.has()) {
[...搭配等].includes() || reject(`unexpected ${}${}等`);
}
}
// 等-韻
for (const [搭配各等, 搭配各韻] of Object.entries(等韻搭配)) {
if (搭配各韻.includes()) {
if (搭配各韻.has()) {
if ([...搭配各等].includes()) {
break;
} else if (搭配各等.includes('三') && === '四' && [...'端透定泥'].includes()) {
} else if (搭配各等.includes('三') && === '四' && new Set('端透定泥').has()) {
break;
}
reject(`unexpected ${}${}等`);
}
}
// 母-呼(基本)、呼-韻
if ([...'幫滂並明'].includes()) {
if (new Set('幫滂並明').has()) {
&& reject('unexpected 呼 for 脣音');
} else if (呼韻搭配.中立.includes()) {
} else if (呼韻搭配.中立.has()) {
&& reject('unexpected 呼 for 開合中立韻');
} else if (呼韻搭配.開合.includes()) {
} else if (呼韻搭配.開合.has()) {
?? reject('missing 呼');
} else {
for (const 搭配呼 of ['開', '合'] as const) {
if (呼韻搭配[搭配呼].includes()) {
if (呼韻搭配[搭配呼].has()) {
if ( === 搭配呼) {
break;
} else if () {
Expand All @@ -1017,7 +1017,7 @@ export class 音韻地位 {
// 母-類(基本)、等-類、類-韻(基本)
if ( !== '三') {
&& reject('unexpected 類 for 非三等');
} else if (!鈍音母.includes()) {
} else if (!鈍音母.has()) {
&& reject('unexpected 類 for 銳音聲母');
} else {
const [典型搭配類, 搭配類] = 類搭配(, , );
Expand All @@ -1030,17 +1030,17 @@ export class 音韻地位 {
}

// 母-韻
if ([...'幫滂並明'].includes()) {
[...'之魚殷痕嚴'].includes() && reject(`unexpected ${}韻脣音`);
if (new Set('幫滂並明').has()) {
new Set('之魚殷痕嚴').has() && reject(`unexpected ${}韻脣音`);
} else {
=== '凡' && reject(`unexpected 凡韻非脣音`);
}
if ([...'莊初崇生俟'].includes()) {
if (new Set('莊初崇生俟').has()) {
=== '三' && ['麻', '清', '幽'].includes() && reject(`unexpected ${}${ === '麻' ? '三等' : ''}莊組`);
=== '開' && ['真', '殷'].includes() && reject(`unexpected ${}韻開口莊組`);
} else {
=== '臻' && reject(`unexpected 臻韻非莊組`);
if (!鈍音母.includes()) {
if (!鈍音母.has()) {
=== '庚' && !== '二' && reject(`unexpected 庚韻${}${}母`);
=== '蒸' && === '合' && reject(`unexpected 蒸韻合口${}母`);
}
Expand All @@ -1058,20 +1058,15 @@ export class 音韻地位 {

const marginalTests = [
['陽韻A類', true, === '陽' && === 'A', '陽韻A類'],
[
'端組類隔',
true,
[...'端透定泥'].includes() && ( === '二' || ( === '四' && !等韻搭配..includes())),
`${}${}${}母`,
],
['咍韻脣音', true, === '咍' && [...'幫滂並明'].includes(), `咍韻脣音`],
['端組類隔', true, new Set('端透定泥').has() && ( === '二' || ( === '四' && !等韻搭配..has())), `${}${}${}母`],
['咍韻脣音', true, === '咍' && new Set('幫滂並明').has(), `咍韻脣音`],
['匣母三等', true, === '匣' && === '三', `匣母三等`],
['羣邪俟母非三等', true, !== '三' && [...'羣邪俟'].includes(), `${}${}等`],
['羣邪俟母非三等', true, !== '三' && new Set('羣邪俟').has(), `${}${}等`],
['云母開口', false, === '云' && === '開' && ![...'宵幽侵鹽嚴'].includes(), '云母開口'],
[
'蒸幽韻特殊類',
false,
&& ['蒸', '幽'].includes() && ([...'幫滂並明'].includes() ? !== 'B' : === '開' && === 'B'),
&& ['蒸', '幽'].includes() && (new Set('幫滂並明').has() ? !== 'B' : === '開' && === 'B'),
`${}${}${}類`,
],
] as const;
Expand Down Expand Up @@ -1121,12 +1116,12 @@ export class 音韻地位 {
const = match[6];

if (簡略描述) {
if (! && ![...'幫滂並明'].includes()) {
if ( === '云' && 呼韻搭配.開合.includes()) {
if (! && !new Set('幫滂並明').has()) {
if ( === '云' && 呼韻搭配.開合.has()) {
= '合';
} else {
for (const 搭配呼 of ['開', '合'] as const) {
if (呼韻搭配[搭配呼].includes()) {
if (呼韻搭配[搭配呼].has()) {
= 搭配呼;
break;
}
Expand All @@ -1139,8 +1134,8 @@ export class 音韻地位 {
= '三';
} else {
for (const 搭配等 of ['一', '二', '三', '四'] as const) {
if (等韻搭配[搭配等].includes()) {
if (搭配等 === '三' && [...'端透定泥'].includes()) {
if (等韻搭配[搭配等].has()) {
if (搭配等 === '三' && new Set('端透定泥').has()) {
= '四';
} else {
= 搭配等;
Expand All @@ -1151,7 +1146,7 @@ export class 音韻地位 {
}
}

if (! && === '三' && 鈍音母.includes()) {
if (! && === '三' && 鈍音母.has()) {
const [典型搭配類] = 類搭配(, , );
if (典型搭配類.length === 1) {
= 典型搭配類;
Expand All @@ -1177,21 +1172,21 @@ function 類搭配(母: string, 呼: string | null, 韻: string): [string, strin
return ['B', 'B'];
}
const 含邊緣地位類 = === '蒸' ? 'CB' : 'AB';
if ([...'幫滂並明'].includes()) {
if (new Set('幫滂並明').has()) {
return ['B', 含邊緣地位類];
} else {
return [含邊緣地位類[0], 含邊緣地位類];
}
}
for (const [搭配類, 搭配韻] of [
['C', [...'東鍾之微魚虞廢殷元文歌尤嚴凡']],
['AB', [...'支脂祭真仙宵侵鹽']], // 幽 already handled above (same for 蒸 & 陽)
['A', [...'麻清']],
['B', [...'庚']],
//['CB', [...'蒸']],
//['CA', [...'陽']],
['C', new Set('東鍾之微魚虞廢殷元文歌尤嚴凡')],
['AB', new Set('支脂祭真仙宵侵鹽')], // 幽 already handled above (same for 蒸 & 陽)
['A', new Set('麻清')],
['B', new Set('庚')],
//['CB', new Set('蒸')],
//['CA', new Set('陽')],
] as const) {
if (搭配韻.includes()) {
if (搭配韻.has()) {
return [搭配類, 搭配類];
}
}
Expand Down
Loading

0 comments on commit 8437a0d

Please sign in to comment.