Repository navigation
Expand file tree
/
Copy pathconcept.margo
More file actions
279 lines (235 loc) · 14.6 KB
/
Copy pathconcept.margo
File metadata and controls
279 lines (235 loc) · 14.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
## ## Margo 프로그래밍 언어 사양서 (v0.1)
****** LLVM 이용해 컴파일러 구현 ******
****** 주석은 반드시 영어로 ******
****** README는 README.md와 README.en.md가 있어야 함(국문, 영문)
### 1. 설계 철학 (Philosophy)
* **C-Native:** 모든 데이터는 C와 동일한 메모리 구조를 갖는다. 별도의 래퍼 없이 C 라이브러리를 즉시 호출한다.
* **Zero-Grief:** 메모리 해제(`free`)와 타입 선언의 번거로움을 최소화한다.
* **Hybrid-Flow:** 인터프리터의 속도로 개발하고, 컴파일러의 성능으로 배포한다.
---
### 2. 타입 시스템 (Type System)
#### 2.1 기본 타입
C 언어의 표준 타입을 그대로 계승하며, `Margo` 전용 편의 타입을 추가한다.
* `int`, `char`, `float`, `double`: C ABI와 100% 호환.
* `string`: 내부적으로 `char *`와 동일하나, 할당 시 자동으로 `NULL(\0)` 문자를 관리함.
* `void`: 반환 값이 없음을 명시.
#### 2.2 자동 타입 추론 (Auto-Inference)
* `auto` 키워드를 통해 대입되는 값에 따라 타입을 결정한다.
* `auto x = 10` (int), `auto y = "hi"` (string).
#### 2.3 바이트 패턴 리터럴
* `[0x01, 0b10, 255]`와 같이 정수 상수만 나열된 대괄호는 정적 바이트 배열 리터럴로 해석된다. 각 항목은 0~255 범위여야 한다.
* 컴파일 시 동일 번역 단위의 숨김 `static const uint8_t` 버퍼로 승격되고, (데이터 포인터, 길이) 쌍을 담은 `file_pattern` 뷰로 치환된다. 같은 리터럴은 재사용된다.
* `auto pat = [0xDE, 0xAD, 0xBE, 0xEF]`처럼 일반 변수에도 대입할 수 있으며, `file/core` 헬퍼의 패턴 인자로 곧바로 전달할 수 있다.
#### 2.4 즉석 열거 리터럴
* `for`-`in` 구문에서 사용하는 `[expr1, expr2, ...]` 형태는 Python 스타일 리스트에 대응하는 설탕이다.
* 각 항목은 상수일 필요가 없으며, 좌→우 순서대로 평가한 뒤 동일 스코프에 숨김 `static const` 버퍼를 생성한다.
* 리스트의 원소 타입은 공통 슈퍼 타입(`auto`→`__auto_type`)으로 추론되며 루프 바디에서 읽기 전용 값으로 노출된다.
---
### 3. 메모리 관리 (Memory Management)
#### 3.1 스코프 기반 자동 해제 (RAII)
* `alloc()` 또는 `alloc_and_init()`으로 할당된 모든 메모리는 해당 변수가 선언된 블록(`{ }`)이 끝나는 지점에서 컴파일러가 자동으로 `free()`를 삽입한다.
* 사용자가 명시적으로 `free()`를 호출할 필요가 없으며, 이는 런타임 오버헤드 없이 컴파일 타임에 결정된다.
#### 3.2 포인터 추상화 (Weird Pointer)
* 다중 포인터(Double Pointer 등)를 직관적으로 다루기 위해 `weird(타입, 차원)` 문법을 사용한다.
* `weird(char, 2)`는 C의 `char **`와 동일하게 컴파일된다.
---
### 4. 제어 흐름 (Control Flow)
#### 4.1 암시적 루프 변수 (Implicit Loop Variable)
* `for` 문에서 선언 없이 사용된 변수는 해당 루프 전용 로컬 변수로 자동 생성된다.
* 예: `for x=0; <10; ++` (여기서 `x`는 루프 안에서만 유효함).
#### 4.2 조건부 증감식
* 증감식 위치에 삼항 연산자나 조건문을 사용하여 복잡한 루프 로직을 한 줄로 표현할 수 있다.
* 예: `count.odd? ++ : +=2`
#### 4.3 행렬 순회 전용 구문
* `mat_find(arr, target, precision = 0) { ... }`
* `arr`가 몇 차원 배열인지, 각 축의 길이가 무엇인지는 컴파일러가 타입 정보(`weird` 축약 포함)와 상수 길이 정보를 바탕으로 계산한다. 사용자는 반복 횟수나 중첩 루프를 직접 명시할 필요가 없다.
* 모든 요소를 순회하면서 `abs(value - target) <= precision`을 만족하는 첫 지점을 찾는다. 일치하는 값이 있을 때만 블록이 실행된다.
* 블록 내부에는 읽기 전용 암시 변수 `mat_value`(일치한 실제 값)와 `mat_index`(각 축 좌표를 담고, 배열처럼 `mat_index[축]`으로 접근 가능한 구조체)가 제공된다.
* 예: `mat_find(weights, 12.34, 0.01) { print("near hit:", mat_value, "at", mat_index[0], mat_index[1]) }`
* `mat_for(arr, func)`
* `arr`의 차수를 자동 추론한 뒤, 차수만큼의 인덱스를 함수 인자로 넘기면서 전 영역을 순회한다. 이때 마지막 인자는 선택적으로 실제 요소 값을 받을 수 있다.
* `func`의 반환 타입이 `bool`이면 `false`를 반환하는 순간 순회를 즉시 중단한다. (반환형이 `void`거나 다른 타입이면 순회는 끝까지 수행된다.)
* 모든 `mat_*` 블록은 행렬을 선형대수학 관점에서 평탄화해 캐시 친화적인 루프를 만들도록 최적화된다.
* 2차원 행렬에서 대각선을 검사하는 예시는 다음과 같다.
```margo
fn diag_only(size_t i, size_t j, double cell) bool {
if i == j {
print("diag", i, j, "=", cell)
}
return true // true → 계속 순회, false → 조기 중단
}
mat_for(matrix2d, diag_only)
```
#### 4.4 근접 이웃 조회 (`mat_neighbor`)
* `mat_for` 바디 안에서는 인자를 생략한 `mat_neighbor()` 호출이 허용된다. 이 경우 컴파일러가 현재 순회 중인 행렬 레퍼런스와 좌표(`mat_index`)를 자동으로 주입해, 기본 반경 `n = 1`인 이웃 뷰를 돌려준다.
* 스코프 밖에서는 `mat_neighbor(arr, i, j, ..., n | seek_fn = fn)` 형태로 호출한다.
* `arr` 뒤에 오는 인자들은 배열의 차수와 동일한 개수의 좌표여야 하며, 마지막 위치 인자는 `seek_fn = some_fn`으로 끝나지 않는 한 반경 `n`으로 간주된다. `seek_fn`이 존재하면 모든 좌표 인자는 차수에 정확히 대응해야 하고, `n`은 생략된다.
* 반경 `n`은 각 축별로 `index - n ... index + n` 범위를 검사하는 초입방(hypercube) 기준이다. 경계를 벗어나는 좌표는 자동으로 잘려나간다.
* `seek_fn`은 `fn bool matcher(mat_neighbor_cell cell)` 형태를 따른다. `cell.index`(각 축 좌표), `cell.value`, `cell.distance`(현재 중심과의 L∞ 거리) 등을 보고 `true`인 셀만 결과에 포함할 수 있다.
* 반환 값은 읽기 전용 `neighbor_view`로, 다음과 같은 유틸리티를 노출한다.
* `neighbor_view.count` — 현재 캡처된 이웃 수.
* `neighbor_view[k].value` / `neighbor_view[k].index[d]` — k번째 이웃의 값 및 d축 좌표.
* `neighbor_view.for_each(fn)` — `fn(cell)` 시그니처를 가지는 함수를 호출해 순회(일찍 `false`를 반환하면 중단).
* 사용 예:
```margo
mat_for(field3d, fn(i, j, k, cell) bool {
auto neigh = mat_neighbor() // 현재 i,j,k 기준 기본 반경
neigh.for_each(fn(nc) {
if nc.value > cell {
print("raise", nc.index[0], nc.index[1], nc.index[2])
}
})
auto strict = mat_neighbor(field3d, i, j, k, seek_fn = is_diagonal) // 사용자 정의 필터
return true
})
```
#### 4.5 행렬 코어 유틸리티 (`@import matrix/core`)
* `matrix_fill(rows, cols, value)`
* 지정된 차수의 새 `auto_matrix`를 RAII 규칙에 맞춰 할당하고 모든 셀을 `value`로 초기화한다.
* 결과는 일반 배열과 동일하게 `grid[i][j]` 접근이 가능하며 `mat_for`, `mat_find`, `mat_neighbor`와 즉시 호환된다.
* `matrix_identity(size, diag_value = 1)`
* `size × size` 단위 행렬을 생성한다. `diag_value`는 주대각선 초기화 값이며, 나머지 셀은 0으로 채워진다.
* 그래프 가중치 정규화, 회전/스케일링 행렬 부트스트랩 등에 활용할 수 있다.
* `matrix_mul(lhs, rhs)`
* `lhs`(m×k)와 `rhs`(k×n)의 곱을 계산해 새 행렬을 반환한다.
* 차수가 맞지 않으면 의미 분석 단계에서 진단을 발생시키며, 연산 중에는 캐시 친화적인 평탄화 전략을 따른다.
* `matrix_transpose(matrix)`
* 데이터를 복사하지 않고 축을 뒤집은 뷰를 돌려준다. 트랜스포즈된 결과 역시 `auto_matrix`로 간주한다.
* `matrix_map(matrix, fn mapper)`
* 동일 차수의 새 행렬을 생성하며 각 요소마다 `mapper(mat_neighbor_cell cell)`을 호출해 반환값을 채운다.
* `mapper`는 `cell.value`, `cell.index[*]`, `cell.distance`를 참고할 수 있어 이웃 민감한 변환을 쉽게 조합할 수 있다.
#### 4.5 리스트 기반 `for-in` 구문
* `for value in [1, 2, heavy_calc(), 4] { ... }`처럼 Python과 유사한 열거식을 지원한다.
* 대괄호 안 표현식은 좌→우 순서대로 평가되어 숨김 상수 배열에 보관되며, 반복문은 해당 배열 길이만큼 순회한다.
* `value` 식별자는 읽기 전용이며 `auto`로 선언하면 항목 타입을 그대로 추론한다. 서로 다른 타입이 혼합되면 공통 슈퍼 타입(`double`과 `int` → `double`)으로 승격된다.
* 향후에는 일반 배열/슬라이스/`file_pattern` 등 임의의 컨테이너에도 확장할 계획이지만, v0.1에서는 리스트 리터럴에 최적화된 구현부터 제공한다.
---
### 5. 외래 함수 인터페이스 및 지시자 (Directives)
#### 5.1 @import 시스템
* `@import c/`: 시스템에 설치된 C 헤더를 직접 파싱하여 가져온다.
* `@import c++/`: C++ 클래스와 함수를 바인딩한다.
* `@import godmode`: 모든 표준 라이브러리와 제약 없는 포인터 연산을 허용한다.
#### 5.2 @style 지시자
* 특정 코드 블록의 문법 엄격도를 조절한다.
* `@style c { ... }`: 이 블록 안에서는 세미콜론과 명시적 타입 선언이 강제된다. (기존 C 코드 복사 붙여넣기 용도)
---
### 6. 통합 도구 (Integrated Tools)
* **Autocorrect:** `@set autocorrect on` 설정 시, `fzf`(퍼지 파인더) 엔진을 활용하여 오타가 난 함수나 변수명을 컴파일 타임에 자동으로 교정 제안하거나 수정한다.
---
### 7. 파일 패턴 탐색 (`@import file/core`)
* `@import file/core`는 `<stdio.h>` 기초와 함께 패턴 검색 전용 런타임(`file_pattern`, `seek_from_file`, `pos_from_file`, `jmp_from_file`)을 노출한다.
* `file_pattern`은 `uint8_t *data`와 `size_t len`을 가진 경량 뷰다. `[0x01, 0x02]` 같은 리터럴은 자동으로 이 타입으로 승격되며, 기존 버퍼와 길이를 명시적으로 넘겨도 된다.
* 공통 동작
* 모든 함수는 `FILE *stream`과 `file_pattern pattern`을 인자로 받는다.
* 검색은 현재 파일 포인터에서 EOF까지 수행되며, 내부 버퍼는 `fread`로 스트리밍된다.
* 패턴이 발견되지 않으면 `false` 혹은 `-1`(위치)로 반환되며, 입력이 `null`이거나 길이가 0일 때도 안전하게 실패한다.
* 검색 도중 포인터는 보존되며(`ftell` 저장 후 `fseek`으로 복원), `jmp_from_file`에서만 호출자가 요청할 때 오프셋을 이동한다.
* `bool seek_from_file(FILE *f, file_pattern pat)`
* 패턴 존재 여부만 반환한다. 발견된 경우에도 파일 포인터는 호출 이전 위치로 복구된다.
* `long pos_from_file(FILE *f, file_pattern pat)`
* 패턴이 최초로 등장하는 파일 오프셋(`SEEK_SET` 기준)을 돌려준다. 실패 시 `-1`을 반환하며, 포인터는 복구된다.
* `bool jmp_from_file(FILE *f, file_pattern pat)`
* 내부적으로 `pos_from_file`를 호출한 뒤 성공 시 `fseek(f, offset, SEEK_SET)`으로 파일 포인터를 이동한다.
* 이동에 성공하면 `true`, 패턴이 없거나 `fseek` 실패 시 `false`를 반환한다.
* `bitmask_view return_all_bitmask_offsets(FILE *f, file_pattern pat)`
* 파일 전체를 스캔하면서 패턴이 일치하는 모든 시작 위치를 bool 비트마스크로 돌려준다. `bitmask_view`는 `struct { bool *bits; size_t len; }`으로 표현되며 RAII 규칙을 따른다.
* `bool hits[] = return_all_bitmask_offsets(...)`처럼 배열 선언 구문으로도 받을 수 있으며, 내부적으로 `bitmask_view hits = ...`로 재작성되어 `hits[idx]` 접근을 허용한다.
* `bitmask_view.indices()`는 `0..len-1` 범위를 `for-in` 루프가 소비할 수 있는 가벼운 뷰로 돌려준다.
* 사용 예:
```margo
@import file/core
fn scan_embedded(FILE *bin) bool {
auto signature = [0x7F, 'E', 'L', 'F']
if !seek_from_file(bin, signature) return false
auto pos = pos_from_file(bin, signature)
if pos >= 0 && jmp_from_file(bin, signature) {
print("ELF header @", pos)
}
bool hits[] = return_all_bitmask_offsets(bin, [0x50, 0x4B])
for idx in hits.indices() {
if hits[idx] {
print("ZIP start near", idx)
}
}
return true
}
```
---
### 8. Showcase 예제
#### 8.1 파일 패턴 + 리스트 순회
```margo
@import file/core
@import std/io
fn dump_zip_offsets(string path) {
weird(FILE, 1) fp = fopen(path, "rb")
if !fp return
bool hits[] = return_all_bitmask_offsets(fp, [0x50, 0x4B, 0x03, 0x04])
for idx in [0, 32, 64, 96] {
print("sanity slot ", idx, ": ", hits[idx])
}
for pos in hits.indices() {
if hits[pos] {
print("central dir candidate @", pos)
}
}
fclose(fp)
}
```
#### 8.2 행렬 + 근접 탐색
```margo
fn sum_hotspots(auto_matrix field) {
auto diag_sum = 0
mat_find(field, 10, 0.001) {
print("exact 10 at", mat_index[0], mat_index[1])
}
mat_for(field, fn(i, j, cell) bool {
if i == j { diag_sum += cell }
auto neigh = mat_neighbor()
auto spikes = mat_neighbor(field, i, j, 2, seek_fn = fn(nc) bool { return nc.value > cell })
neigh.for_each(fn(nc) {
if nc.value > cell * 2 {
print("spike: ", nc.value, " near ", i, j)
}
})
if spikes.count == 0 && cell > 0 {
print("isolated hot cell", i, j)
}
return true
})
print("diag sum:", diag_sum)
}
```
---
## ## 종합 예시 코드 (Full Concept)
```margo
@import c/stdio
@import std/io
// 최적화 지시자: if-else를 점프 테이블로 변환 시도
fn @use_switch_optim check_val(int v) {
if v == 1 return 100
else return 0
}
fn start(int argC, char **argV) {
// 1. 자동 할당 및 해제 (RAII)
string msg = alloc_and_init(1024, "Margo Language")
print(msg)
// 2. 암시적 변수 루프
// 'x'는 여기서 자동 생성되고 루프 종료 시 소멸함
for x=0; <5; ++ {
print("순서: " + x.to_string())
}
// 3. C 스타일 혼용 대신 표준 IO 헬퍼 사용
print("숫자를 입력하세요:", endl = " ")
auto temp = 0
Scan(temp)
// 4. 복잡한 증감 로직 루프
auto i = 0
for i < 20; i.odd? ++ : +=3 {
print(i.to_string(), endl = ',')
}
// 5. 다중 포인터 (weird) 사용
auto pp = weird(char, 2)
pp = argV // char ** 대입
// 리턴 SUCCESS(0)는 생략 가능 (암시적 반환)
}
```