├── shook-lang ├── __init__.py └── main.py ├── assets └── shook.png ├── example ├── multiple3by4.shook └── helloworld.shook ├── .gitignore └── README.md /shook-lang/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/shook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pjongy/shook-lang/HEAD/assets/shook.png -------------------------------------------------------------------------------- /example/multiple3by4.shook: -------------------------------------------------------------------------------- 1 | 슉슈슈슈시발럼아 슉슈슈슈슈,우우욱시발럼아 슥,,,시발람아아아시발럼아슉슈슈.. 시발럼아슉슈슈..욱욱,,욱시발럼아 슉슈슈..욱욱,욱시발럼아 슉시발럼아시발롬아 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | **__pycache__/ 3 | **.pyc 4 | **.env 5 | 6 | .idea/ 7 | dist/ 8 | *.egg-info/ -------------------------------------------------------------------------------- /example/helloworld.shook: -------------------------------------------------------------------------------- 1 | 슉슈슈슈.슈시발럼아 슉슈슈..시발럼아슉슈슈슈.우우욱우욱우욱우욱슈슈슈슈시발럼아시발람아시발럼아슉슈슈슈.아욱 시발럼아슉슈슈.욱슈슈 시발럼아시발람아 아아아시발럼아시발람아 시발럼아슉슈슈.욱슈슈슈슈,시발럼아,,,시발람아 시발럼아,,,,,시발람아 시발럼아시발람아아아아아 시발럼아시발람아,아아아시발럼아 시발롬아 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 슉-랭 (Shook lang) 2 | 3 | ## (주의) 욕설이 섞인 밈입니다. [Namuwiki](https://namu.wiki/w/%EC%8A%88%EC%8A%89%20%EC%8A%88%EC%88%99.%20%EC%8A%89.%20%EC%8B%9C.%20%EC%8B%9C%EB%B0%9C%EB%9F%BC%EC%95%84.?from=%EC%8A%89%20%EC%8A%88%EC%8A%89) 4 | 실용적인 프로젝트가 아닙니다. (Inspired by [umjunsik-lang](https://github.com/rycont/umjunsik-lang/)) 5 | 6 | 7 | ## 슈슉 슈숙. 슉. 시. 시발럼아. 8 | ![Shoo-Shook](./assets/shook.png) 9 | 10 | 11 | ## 키워드 12 | ``` 13 | 슉: 변수 대입 선언 14 | 슈: 변수 inc 15 | 아: 변수 dec 16 | .: 변수 **= 2 17 | 18 | (공백): 스택 포인터 += 1 19 | ,: 스택 포인터 -= 1 20 | 21 | 시발럼아 : 스택 포인터가 가리키는 스택 데이터에 변수 대입 22 | 시발람아 : 변수에 스택 포인터가 가리키는 스택 데이터 대입 23 | 24 | 욱: 변수에서 스택 데이터 더하기 25 | 우욱: 변수에서 스택 데이터 빼기 26 | 우우욱: 변수에서 스택 데이터 곱하기 27 | 우우우욱: 변수에서 스택 데이터 나누기 28 | 29 | 슥: 변수를 str형으로 변환 후 스택 포인터 위치에서 역순으로 저장 (산술연산 결과 출력 시 사용) 30 | -: 스택 포인터 변수에 대입 선언 31 | _: 스택 포인터 변수에 대입 완료 32 | 시발롬아: 스택 데이터가 0이거나 스택포인터가 0이 될 때까지 -1 하며 1byte씩 출력 33 | ``` 34 | 35 | ## Demo ( 3 * 4 ) 36 | ``` 37 | // 슉슈슈슈시발럼아 슉슈슈슈슈,우우욱시발럼아 슥,,,시발람아아아시발럼아슉슈슈.. 시발럼아슉슈슈..욱욱,,욱시발럼아 슉슈슈..욱욱,욱시발럼아 슉시발럼아시발롬아 38 | $ python3 -m shook-lang.main --input=example/multiple3by4.shook --debug=False 39 | 12 40 | ``` 41 | 42 | ## Demo ( helloworld ) 43 | ``` 44 | // 슉슈슈슈.슈시발럼아 슉슈슈..시발럼아슉슈슈슈.우우욱우욱우욱우욱슈슈슈슈시발럼아시발람아시발럼아슉슈슈슈.아욱 시발럼아슉슈슈.욱슈슈 시발럼아시발람아 아아아시발럼아시발람아 시발럼아슉슈슈.욱슈슈슈슈,시발럼아,,,시발람아 시발럼아,,,,,시발람아 시발럼아시발람아아아아아 시발럼아시발람아,아아아시발럼아 시발롬아 45 | $ python3 -m shook-lang.main --input=example/helloworld.shook --debug=False 46 | helloworld 47 | ``` 48 | -------------------------------------------------------------------------------- /shook-lang/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from typing import List 3 | 4 | 5 | class Flags: 6 | def __init__(self): 7 | self.variable_assigning = False 8 | 9 | 10 | def _overflow_mask(op: int) -> int: 11 | return op & 0xff 12 | 13 | 14 | class Interpreter: 15 | def __init__(self, stack_max_size=256, debug=False): 16 | self.stack_max_size = stack_max_size 17 | self.stack = [0 for _ in range(self.stack_max_size)] 18 | self.stack_pointer = 0 19 | 20 | self.flags = Flags() 21 | self._variable = 0 22 | self.debug = debug 23 | 24 | def print_memory(self): 25 | stack_memory = ','.join([str(i) for i in self.stack]) 26 | print(f'stack: {stack_memory}') 27 | print(f'variable: {self._variable}') 28 | print(f'stack pointer: {self.stack_pointer}') 29 | print(f'flag(variable_assigning): {self.flags.variable_assigning}') 30 | 31 | def run(self, code: str): 32 | if code == '슉': 33 | assert self.flags.variable_assigning is False 34 | self.flags.variable_assigning = True 35 | self._variable = 0 36 | if code == '슈': 37 | assert self.flags.variable_assigning is True 38 | self._variable += 1 39 | self._variable = _overflow_mask(self._variable) 40 | if code == '아': 41 | assert self.flags.variable_assigning is True 42 | self._variable -= 1 43 | self._variable = _overflow_mask(self._variable) 44 | if code == '.': 45 | assert self.flags.variable_assigning is True 46 | self._variable **= 2 47 | self._variable = _overflow_mask(self._variable) 48 | if code == ' ': 49 | self.stack_pointer += 1 50 | if code == ',': 51 | self.stack_pointer -= 1 52 | if code == '욱': 53 | # Add stack value to variable 54 | assert self.flags.variable_assigning is True 55 | self._variable += self.stack[self.stack_pointer] 56 | self._variable = _overflow_mask(self._variable) 57 | if code == '우욱': 58 | # Minus stack value to variable 59 | assert self.flags.variable_assigning is True 60 | self._variable -= self.stack[self.stack_pointer] 61 | self._variable = _overflow_mask(self._variable) 62 | if code == '우우욱': 63 | # Multiple stack value to variable 64 | assert self.flags.variable_assigning is True 65 | self._variable *= self.stack[self.stack_pointer] 66 | self._variable = _overflow_mask(self._variable) 67 | if code == '우우우욱': 68 | # Divide stack value to variable 69 | assert self.flags.variable_assigning is True 70 | self._variable /= self.stack[self.stack_pointer] 71 | self._variable = _overflow_mask(int(self._variable)) 72 | if code == '시발럼아': 73 | # Assign variable to stack data 74 | assert self.flags.variable_assigning is True 75 | self.stack[self.stack_pointer] = self._variable 76 | self.flags.variable_assigning = False 77 | if code == '시발람아': 78 | # Assign stack data to variable 79 | assert self.flags.variable_assigning is False 80 | self._variable = self.stack[self.stack_pointer] 81 | self.flags.variable_assigning = True 82 | if code == '-': 83 | # Assign stack pointer to variable 84 | assert self.flags.variable_assigning is False 85 | self._variable = self.stack_pointer 86 | self.flags.variable_assigning = True 87 | if code == '_': 88 | # Assign variable to stack pointer 89 | assert self.flags.variable_assigning is True 90 | self.stack_pointer = min(self._variable, self.stack_max_size) 91 | self.flags.variable_assigning = False 92 | if code == '슥': 93 | # Change variable to str type and assign it to stack 94 | string_value = str(self._variable) 95 | for value in reversed(string_value): 96 | self.stack[self.stack_pointer] = int(value) 97 | self.stack_pointer += 1 98 | if code == '시발롬아': 99 | # Print current stack while null access 100 | printing_buffer_pointer = self.stack_pointer - 1 101 | while printing_buffer_pointer >= 0: 102 | element = self.stack[printing_buffer_pointer] 103 | if element == 0: 104 | break 105 | sys.stdout.write(chr(element)) 106 | printing_buffer_pointer -= 1 107 | if self.debug: 108 | print(code) 109 | self.print_memory() 110 | 111 | 112 | def tokenize(code: str) -> List[str]: 113 | tokenized = [] 114 | sibal_ing = False 115 | sibal_stack = [] 116 | woo_stack = [] 117 | for op in code: 118 | if op == '우': 119 | woo_stack.append(op) 120 | elif op == '욱': 121 | woo_stack.append(op) 122 | tokenized.append(''.join(woo_stack)) 123 | woo_stack = [] 124 | elif op == '시': 125 | assert sibal_ing is False 126 | sibal_ing = True 127 | sibal_stack.append(op) 128 | elif op == '발': 129 | assert sibal_stack[-1], '시' 130 | sibal_stack.append(op) 131 | elif op in ['럼', '롬', '람']: 132 | assert sibal_stack[-1], '발' 133 | sibal_stack.append(op) 134 | elif op == '아' and sibal_ing: 135 | if sibal_stack[-1] not in ['럼', '롬', '람']: 136 | raise AssertionError('럼,롬,람 should already be set') 137 | sibal_stack.append(op) 138 | tokenized.append(''.join(sibal_stack)) 139 | sibal_stack = [] 140 | sibal_ing = False 141 | else: 142 | tokenized.append(op) 143 | return tokenized 144 | 145 | 146 | def main(input_file: str, debug: bool = False): 147 | with open(input_file, 'r') as shook: 148 | code = shook.read() 149 | thread = Interpreter(20, debug) 150 | for op in tokenize(code): 151 | thread.run(op) 152 | 153 | 154 | if __name__ == '__main__': 155 | import argparse 156 | 157 | parser = argparse.ArgumentParser(description='Shook-lang runtime') 158 | parser.add_argument('--input', default='multiple3by4.shook', help='Pass input .shook file') 159 | parser.add_argument('--debug', default='False', help='Debug flag (True/False)') 160 | args = parser.parse_args() 161 | main(args.input, args.debug == 'True') 162 | --------------------------------------------------------------------------------