伍什

From Esolang
Jump to navigation Jump to search

This page is working in progress.

伍什(wǔshí, or literally five and ten with 'human' radical) is an esolang using CJK characters as commands.

About CJK characters

According to context, CJK characters may also be called Hanzi(for Chinese), Kanji(for Japanese), or Hanja(for Korean).

You may have noticed that the characters 伍 and 什 consists of 2 parts: 亻and another part. This is because Many of CJK characters are phono-semantic, meaning that parts of the character indicates its (ancient) pronunciation and other parts indicates its meaning category. For instance, 伍 consists of 亻 and 五, where 亻(actually a flat 人) shows that it has something to do with humans, and 五(wǔ) shows that it sounds similar to wǔ. As a result, 伍 resembles queue / army.

Our goal is to make use of the phonetic part. Think about it: the semantic part shared by many chars could pe the operator; why don't we see the phonetic part as the operand?

Commands, types and errors

Under construction

A command is constructed with operators and its objects, separately left value(literally on its left) and operand(on the right) if they both exist. The reason for only calling the latter an 'operand', is that only this can concatenate with the operand, by character manners(but does nothing with geometric positions inside the glyph). For example suppose that 我(I) am some kind of operator(sadly we don't have that, it's Syntax Error), and 我 work with 鳥/鸟(bird)s. The original command is 鸟我鸟, and 我 can merge with the latter 鸟 to form 鹅/鵝/䳘/鵞/䳗 (all variants of the character for goose; only the first two are still used often), so this beomes 鸟鹅 or the other four cases. However the former 鸟 never merges with 我, so 鹅鸟, or even 䳘鸟 is unacceptable. The exception is branching command 辵, where its 'left' value is actually the command block on right of the operand.

Commands can be separated by newline or any full-width unpaired punctuation such as ,。?!;:—…(Note: in formal Chimese text …… and —— ought to be doubled, but this language doesn't require that. Since multiple such punctuations are seen as empty commands, or NOPs, the 'formal' practice works anyway.). Full-width brackets like ()【】 can be used to mark blocks for branching commands(while half-width () is used to prioritize operations)(empty blocks work as NOPs as well). Full-width quotes like ‘’“” are used to mark literal strings(escapes like \n, \‘ or \u4e00 are supported), the only difference is that “” can mark multiline ones, just as what triple quote does in Python.

Just like in Python, when new unmentioned single-part characters or components appear, they are considered new auto-type variables. Types currently include int, float and string. There is no explict conversion between types, so if you want to convert types you have to do as follows(All additions are switchable):

How to convert types
↓From To→ Int Float String
Int As-is [Expr]金0.0 ‘’金[Expr]
Float [Expr]炎1 # Floored As-is ‘’金[Expr] # With double precision
String Write it yourself(see example) Write it youself As-is

A number literal value can (but not necessarily) be written in chars. 3076 == 三〇七六 == 三0七6, and 24.91 == 二四.九一. 零 and 点/點 are avoided for they have parts similar to operators. There is a constant keyword 不, which is equal to any False value(including 0, 0.0 and ‘’), so 广[Expr] can be replaced with ([Expr])肧.

Priorities works differently according to how you write the code. A single character is considered a whole, just like 㭅 as (-3) (but this is not seen as a negative! If you need one please use left value 0), so even a prior operator cannot get this operand as its left value; but when you tear it apart, everything works according to priority. This may save you some brackets while causing some headache, so if you're unsure, just split everything, follow general priorities, and make lots of (bracket)s. Example: 三㭅氿 → 3 -3 *9 → (3 - 3) * 9 → 0, while 三木三氿 → 3 - 3 *9 → 3 - 3 * 9 → -24.

Note that 'associativity' only means that if the operator is separate from operand how should it associate. It has nothing to do with its position in a compound character.

Comments start with #. Like Python, you may also create a single unassigned string as comment.

Characters may appear different in Traditional/Simplified Chinese, Japanese or Korean. Please take this into account when programming with this.

Component Commands
Operator part Associativity Meaning Example
人(亻) Left Input to variables. The operand is taken as a single-char variable name. Any input is considered strings, separated by newlines(not included). (Then the name of this esolang is actually a Syntax Error: You cannot input into a number!) After each input, stdin(人) is returned so more variables receive input. 你少 or 人尔少 takes 2 inputs and stores them in var 尔, 少.
言(讠) Left Output from operand. The operand can be literal numbers, literal strings, variables or complex expressions. After each output, stdout(言) is returned so more variables receive output. Note that 言 adds no indentations, so you have to add spaces and ‘\n’s by hand. 說事, 说事, 言兑事 or 讠兑事 outputs value of var 兑, 事.
Right Assignment. Takes its operand and assign it to the character on the left. Inferior to 金/木. Not to be confused with 囗. 天口上口下叭 assigns 天, 上 and 下 with integer 8.
金(钅) Left Addition. Adds its operand to its left value and returns the result. Also used to concatenate strings, when either left value or operand is a string. 三釚钟 or 三金九金中 returns 3 + 9 + 中.
Left Subtraction. 三㭅样 or 三木三木羊 returns 3 - 3 - 羊.
水(氵) Left Multiplication. Prior to 金/木. Also used to repeat strings, where its operand is the number. 三氿洗, 三氵九氵先 or 三水九水先 returns 3 * 9 * 先.
火(灬) Left Float division. As in Python, any input returns a float. Prior to 金/木. 三燤, 三火萬 or 三火万 returns 3 / 10000 = 0.0003.
Left Truncated division. As in Python, output is floored, but here it is int type. Prior to 金/木. 九炎二 returns 9 // 2 = 4.
Left Modulo. Accepts integer or float, returns int; result sign is identical to operand. Prior to 金/木. 三四五六圲 returns 3456 % 1000 = 456.
Left Greater than. If Left value is greater than operand(by value for values, or by Unicode dict order for strings), return 1, else return 0. 三旦 returns 3 > 1 = 1.
Left Equals. If Left value is equal to operand, return 1, else return 0. 九肍 returns 1.
Left Greater than or equals. Can be split into 日月. 十盟, 十明皿 or 十日月皿 returns 1 for any 皿 value <= 10.
广 Right Not(by boolean). Returns 1 if the operand is False value, else return 0. Can concatenate with 日, 月 etc if possible. 三㡺 return 3 <= 1 = 0.
辵(辶) - If statement. Takes its operand as condition, and if it returns False value, the If block is jumped over. Must be paired up with 走. 边【...】䞜 is executed once if var 力 is not 0 or empty string.
- 'Jumpback' operation. Takes its operand as condition, and if it returns True value the flow jumps back to the 辵 it is paired up with. In the last example, 走 receives 不, so it is simply an If-equivalent. To create endless loop you can use 辷【...】走一.
- Break operation. Takes its operand as conditon, and if it returns True value the flow jumps out of the 辵-走 pair. If 石 is out of any pair, with a True operand it halts the program. 破 will do that if 皮 is True value.
刀(刂) Left Single character slicing. Left value should be a string, and the operand should be one single index integer(starting from 0). Returns a single-char string(SCS). If the number is out of index, the operation simply returns empty string ‘’. ‘不要断章取义’𬺳 returns ‘不要断章取义’[1] = ‘要’.
示(礻) Right Int and SCS mutual convertion by Unicode value. If length of string operand is other than 1, returns -1; if int is out of current Unicode range(0 to 0x10ffff), returns empty string ‘’. 示一九九六八 = ‘一’, while 示‘一’ = 19968.

Luckily for non CJK character users, the real meaning of characters are not important(if you just write programs without appreciating it from Aesthetics prospective), you only care about the glyphs.

Any command containing radicals not mentioned above(e.g. 鱼 or 鱿), or multiple operators in one character(e.g. 俐 = 人刀禾), are considered Syntax Error. Dividing by 0 raises Math Error, and trying to operate wrong types(e.g. ‘str1’火‘str2’ or 三明‘治’) raises Type Error.

Example Programs

Warning: None of the following programs are tested. If there's any mistake, feel free to edit!

Hello, world!

言‘Hello, world!’

This outputs a single Hello, world!.

99 bottles of beer (without final verse)

甲口99
辷【
  辵(甲旦)言(甲金‘bottles’)䞜
  辵(甲㡺)言(甲金‘bottle’)䞜
  言‘ of beer on the wall,\n’
  辵(甲旦)言(甲金‘bottles’)䞜
  辵(甲㡺)言(甲金‘bottle’)䞜
  言‘ of beer.\nTake one down, pass it around, ’
  甲口甲本      # 本 = 木一. Note that this cannot be compressed as 甲呷本, as 甲呷 will be executed first.
  辵(甲旦)言(甲金‘bottles’)䞜
  辵(甲月一)言‘1 bottle’䞜
  辵(庘)言‘No bottles’䞜
  言‘ of beer on the wall.\n\n’
】走甲

Quine

This is inspired by the wiki's 'Quinify' tutorial.

甲口“言(‘甲口’金示八二二〇钾金示八二二一金‘,’钾)”,言(‘甲口’金示八二二〇钾金示八二二一金‘,’钾)

Cat program

辷【倓?谈!】走一

Input to int convertion

Only if the input is pure Arabic number sequence will the program run through, otherwise it fails and alerts.

他
甲口至口出口羊口0
辷【
    子口示也到
    辵(子月0本)出叶䞜
    子口子木四八
    辵((子广明0)金(子旯))【出叶,羊叶】䞜
    础
    甲口甲汁钾
    至口至金一
】走一
辵羊言‘Cannot convert!’䞜
辵庠言甲䞜

Truth machine

亿
辵乙【言一】走一
辵广乙【言〇】䞜

Intepreter

There is unlikely any intepreter for this esolang, because dividing CJK characters alone is not only huge work, but can be ambiguous at times. But if we introduce more restrictions, it is still possible to make one using some online glyph database.