Trang Language
Trang là ngôn ngữ kịch bản minimalist được nhúng trong thinsh (tiny shell), kết hợp sức mạnh của shell UNIX với khả năng lập trình có cấu trúc. Trang cung cấp cú pháp tiếng Việt đơn giản để viết các script tự động hóa, xử lý logic phức tạp, và tương tác trực tiếp với hệ thống Linux.
Ngôn ngữ chạy trên một stack-based virtual machine với bytecode được biên dịch
thời gian chạy, cho phép thực thi nhanh và cô lập môi trường thông qua khối trang.
Tính năng chi tiết
1. Biến & Biểu thức số nguyên
Trang hỗ trợ biến số nguyên với cú pháp gán đơn giản và các toán tử số học, logic cơ bản.
Khả năng:
- Toán tử số học:
+,-,*,/ - Toán tử so sánh:
<,>,== - Biến tự động khởi tạo = 0
- Hỗ trợ biểu thức lồng nhau với dấu ngoặc
# Biến và biểu thức
x = 10
y = x * 2 + 5
result = (x + y) / 3
# So sánh
isGreater = x > 5 # 1 (true) hoặc 0 (false)
isEqual = x == 10 # 1
in x # In: 10
in y # In: 25
in result # In: 11
2. Cấu trúc điều khiển
Hỗ trợ rẽ nhánh neu...thi...het và vòng lặp khi...thi...het
với cú pháp tiếng Việt tự nhiên.
Rẽ nhánh (neu-thi-het):
x = 15
neu x > 10 thi
in x
in 1
het
# Nested conditions
neu x > 5 thi
neu x < 20 thi
in 999
het
het
Vòng lặp (khi-thi-het):
# Fibonacci(20)
n = 20
a = 0
b = 1
i = 0
khi i < n thi
t = a + b
a = b
b = t
i = i + 1
het
in a # 6765
3. Khối sandbox (trang...het)
Tính năng độc đáo: tạo môi trường cô lập để thực thi code, trả về giá trị mà không ảnh hưởng đến state bên ngoài.
Cơ chế hoạt động:
- Backup toàn bộ stack và biến hiện tại
- Reset môi trường sandbox (biến = 0, stack rỗng)
- Thực thi code trong sandbox
- Lấy giá trị top-of-stack làm return value
- Restore state bên ngoài
- Push return value lên stack ngoài
x = 10
in x # 10
# Sandbox thay đổi x bên trong
y = trang
x = 999 # x local trong sandbox
123 # return value
het
in y # 123 (return value từ sandbox)
in x # 10 (x ngoài không đổi!)
# Factorial trong sandbox
fact10 = trang
n = 10
acc = 1
i = 1
khi i < n + 1 thi
acc = acc * i
i = i + 1
het
acc # return value
het
in fact10 # 3628800
4. Tích hợp lệnh shell
Gọi trực tiếp các lệnh Linux từ script Trang, kết hợp scripting với automation.
Lệnh builtin hỗ trợ:
date- Hiển thị thời gian hệ thốngpwd- Thư mục hiện tạiwhoami- Tên userls,dir- Liệt kê filesps- Danh sách processescd,exit,help,history
i = 0
khi i < 5 thi
date # In timestamp
pwd # In working directory
in i
i = i + 1
het
whoami # In username
ls # List files
5. Quản lý jobs (Background/Foreground)
Shell hỗ trợ chạy processes ở background và quản lý jobs như bash.
Chức năng:
- Chạy nền:
command & - Foreground:
fg <job_id> - Kill, stop, resume processes
- Xử lý SIGINT (Ctrl+C) cho child process
- Job table tracking
# Trong thinsh
thinsh> sleep 100 &
[1] Running: sleep 100
thinsh> ps
# Xem processes
thinsh> fg 1
# Đưa job 1 lên foreground
# Ctrl+C để kill process
6. Biến môi trường riêng
Quản lý biến môi trường độc lập với bash, lưu persistent trong env.txt.
Commands:
set <key> <value>- Đặt biếnget <key>- Xem giá trị- Lưu vào
env.txtdạngKEY=VALUE
thinsh> set API_KEY abc123
thinsh> set PORT 8080
thinsh> get API_KEY
abc123
thinsh> get PORT
8080
Kiến trúc nội bộ
Stack Virtual Machine
Trang sử dụng stack-based VM để thực thi bytecode, tương tự JVM hoặc Python bytecode interpreter.
Cấu trúc VM (MAY_AO):
| Thành phần | Mô tả | Kích thước |
|---|---|---|
stack[1024] |
Stack chính cho tính toán | 1024 int |
vars[1024] |
Mảng biến toàn cục | 1024 int |
pc |
Program counter (chỉ số instruction) | int |
sp |
Stack pointer (đỉnh stack) | int |
backup_* |
Backup cho sandbox restoration | 1024 int × 2 |
Triển khai (C source):
typedef struct {
CHUONG_TRINH *program;
int pc;
int stack[1024];
int sp;
int backup_stack[1024];
int backup_sp;
int vars[1024];
int backup_vars[1024];
int is_in_trang;
} MAY_AO;
void push(MAY_AO *vm, int value) {
if (vm->sp >= 1024) {
printf("Loi: Tran ngan xep (Stack Overflow)!\n");
exit(1);
}
vm->stack[vm->sp++] = value;
}
int pop(MAY_AO *vm) {
if (vm->sp <= 0) {
printf("Loi: Ngan xep rong (Stack Underflow)!\n");
exit(1);
}
return vm->stack[--vm->sp];
}
Compiler (Lexer + Parser)
Compiler phân tích source code Trang thành bytecode, thực hiện lexical analysis và parsing one-pass.
Các giai đoạn:
- Lexer: Tokenize source thành tokens (keywords, operators, identifiers, numbers)
- Parser: Phân tích cú pháp và sinh bytecode
- Emission: Ghi opcodes vào
program->code[]
Keywords được hỗ trợ:
typedef enum {
TOKEN_NEU, // if
TOKEN_THI, // then
TOKEN_HET, // end
TOKEN_KHI, // while
TOKEN_TRANG, // sandbox
TOKEN_IN, // print
TOKEN_EQUAL, // =
TOKEN_SEMICOLON,
TOKEN_PLUS, TOKEN_MINUS, TOKEN_STAR, TOKEN_SLASH,
TOKEN_LESS, TOKEN_GREATER, TOKEN_EQUAL_EQUAL,
TOKEN_LPAREN, TOKEN_RPAREN,
TOKEN_VAR, TOKEN_NUMBER,
TOKEN_EOF, TOKEN_ERROR, TOKEN_NEWLINE
} TU_KHOA;
static const char *keyword_names[] = {
"neu", "thi", "het", "khi", "trang", "in"
};
Symbol table:
- Mảng 1023 slots cho biến user
- Slot 1023 dành riêng cho return value của
trang - Hash table đơn giản: key → slot index
Opcodes (Instruction Set)
VM định nghĩa 17 opcodes cơ bản cho arithmetic, logic, control flow và sandbox.
| Opcode | Mô tả | Thao tác stack |
|---|---|---|
NAP |
Load constant lên stack | push(const[operand]) |
LAY |
Load biến lên stack | push(vars[operand]) |
CAT |
Store giá trị vào biến | vars[operand] = pop() |
CONG |
Cộng | push(pop() + pop()) |
TRU |
Trừ | b=pop(); a=pop(); push(a-b) |
NHAN |
Nhân | push(pop() * pop()) |
CHIA |
Chia (kiểm tra /0) | b=pop(); a=pop(); push(a/b) |
BANG |
So sánh == | push(pop() == pop()) |
LON |
So sánh > | b=pop(); a=pop(); push(a>b) |
NHO |
So sánh < | b=pop(); a=pop(); push(a<b) |
NHAY |
Jump vô điều kiện | pc = operand |
NNS |
Jump if false (0) | if (!pop()) pc = operand |
IN |
Print giá trị / exec cmd | operand=0: print; =1: exec |
BO |
Pop và discard | pop() |
VAO_TRANG |
Enter sandbox | Backup state, reset stack/vars |
RA_TRANG |
Exit sandbox | Restore state, push return value |
DUNG |
Halt VM | Exit main loop |
Implementation (VM dispatch loop):
void run(MAY_AO *vm) {
while (vm->pc < vm->program->code_size) {
CHI_DAN instr = vm->program->code[vm->pc];
vm->pc++;
switch (instr.opcode) {
case CONG: OP_CONG(vm); break;
case TRU: OP_TRU(vm); break;
case NHAN: OP_NHAN(vm); break;
case CHIA: OP_CHIA(vm); break;
case BANG: OP_BANG(vm); break;
case LON: OP_LON(vm); break;
case NHO: OP_NHO(vm); break;
case NHAY: OP_NHAY(vm, instr.operand); break;
case NNS: OP_NNS(vm, instr.operand); break;
case CAT: OP_CAT(vm, instr.operand); break;
case LAY: OP_LAY(vm, instr.operand); break;
case NAP: OP_NAP(vm, instr.operand); break;
case BO: OP_BO(vm, instr.operand); break;
case IN: OP_IN_WITH_OPERAND(vm, instr.operand); break;
case VAO_TRANG: OP_VAO_TRANG(vm); break;
case RA_TRANG: OP_RA_TRANG(vm); break;
case DUNG: return;
default:
printf("Loi: Opcode khong hop le!\n");
exit(1);
}
}
}
Sandbox Mechanism (trang...het)
Cơ chế sandbox được triển khai thông qua 2 opcodes: VAO_TRANG và RA_TRANG.
Luồng thực thi:
- Compile time: Emit VAO_TRANG → sandbox_code → RA_TRANG
- Runtime (VAO_TRANG):
- Check nested trang (forbidden)
- Backup
sp,stack[0..sp],vars[0..1024] - Reset
sp=0,vars[]=0 - Set
is_in_trang=1
- Runtime (RA_TRANG):
- Capture
result = stack[sp-1](if sp > 0) - Restore
sp,stack[],vars[] - Set
is_in_trang=0 - Push
resultonto restored stack
- Capture
void OP_VAO_TRANG(MAY_AO *vm) {
if (vm->is_in_trang) {
printf("Loi: Khong ho tro 'trang' long nhau!\n");
exit(1);
}
vm->is_in_trang = 1;
// Backup outer state
vm->backup_sp = vm->sp;
for (int i = 0; i < vm->backup_sp; i++) {
vm->backup_stack[i] = vm->stack[i];
}
for (int i = 0; i < 1024; i++) {
vm->backup_vars[i] = vm->vars[i];
}
// Fresh sandbox state
vm->sp = 0;
for (int i = 0; i < 1024; i++) {
vm->vars[i] = 0;
}
}
void OP_RA_TRANG(MAY_AO *vm) {
if (!vm->is_in_trang) {
printf("Loi: 'ra_trang' khi khong o trong 'trang'!\n");
exit(1);
}
// Capture return value
int has_result = (vm->sp > 0);
int result = has_result ? vm->stack[vm->sp - 1] : 0;
// Restore outer state
vm->sp = vm->backup_sp;
for (int i = 0; i < vm->backup_sp; i++) {
vm->stack[i] = vm->backup_stack[i];
}
for (int i = 0; i < 1024; i++) {
vm->vars[i] = vm->backup_vars[i];
}
vm->is_in_trang = 0;
// Push return value onto restored stack
push(vm, result);
}
Hướng dẫn sử dụng
Build từ source
# Build with readline (recommended)
make
# Build without readline
USE_READLINE=0 make
# Clean build artifacts
make clean
Chạy shell interactively
./thinsh
# Shell hỗ trợ:
# - Lệnh Linux: ls, date, ps, pwd, whoami, ...
# - Builtins: cd, exit, help, history, set, get
# - Background jobs: command &
# - Job control: fg
# - Keyboard navigation: ↑↓←→ (với readline)
# - Tab completion (với readline)
Chạy script Trang
# Trong thinsh shell
thinsh> trang script.trang
# Hoặc redirect stdin
./thinsh < script.trang
Ví dụ đầy đủ
Fibonacci sequence
# fib_checkpoints.trang
n = 25
i = 0
a = 0
b = 1
khi i < n thi
t = a + b
a = b
b = t
# In một vài giá trị đầu và cuối
neu i < 5 thi
in i
in a
het
neu i > 20 thi
in i
in a
het
i = i + 1
het
in a # F(25) = 75025
GCD (Greatest Common Divisor)
a = 1071
b = 462
# Tính GCD trong sandbox
g = trang
x = a
y = b
khi y > 0 thi
q = x / y
r = x - (q * y)
x = y
y = r
het
x # return GCD
het
in a # 1071
in b # 462
in g # 21
Collatz conjecture
n0 = 27
steps = trang
n = n0
s = 0
khi n > 1 thi
# Kiểm tra chẵn/lẻ
q = n / 2
r = n - (q * 2)
neu r == 0 thi
n = q # n chẵn: n = n/2
het
neu r > 0 thi
n = (3 * n) + 1 # n lẻ: n = 3n+1
het
s = s + 1
het
s # return số bước
het
in n0 # 27
in steps # 111
Transaction simulation
balance = 1000
amount = 275
# Kiểm tra và thực hiện giao dịch trong sandbox
newBalance = trang
b = balance
fee = 3
tentative = b - amount - fee
# Nếu không đủ tiền, trả về balance cũ
neu tentative < 0 thi
b
het
# Nếu đủ, trả về balance mới
tentative
het
balance = newBalance
in balance # 722 (1000 - 275 - 3)
Integration with shell commands
i = 0
x = 10
sum = 0
khi i < 10 thi
date # In timestamp
pwd # In current directory
in i
# Tính score trong sandbox
score = trang
t = i * i
neu t > 20 thi
t + x
het
t + x # Luôn return một giá trị
het
in score
sum = sum + score
i = i + 1
het
in sum
Hạn chế & Phát triển tương lai
Hạn chế hiện tại
- Chỉ hỗ trợ kiểu dữ liệu
int(không có string, float, array) - Không có
else/elif(chỉ cóneu-thi-het) - Không có
forloop (chỉ cókhiwhile loop) - Sandbox không lồng nhau được
- Không có functions/procedures (chỉ có sandbox blocks)
- Stack và vars giới hạn 1024 elements
- Không có module system / import
Khả năng mở rộng
- Kiểu dữ liệu: Thêm string, float, arrays với tagged union
- Functions: Implement call stack và
ham...hetkeyword - Control flow: Thêm
khac(else),break,continue - I/O: File operations, network primitives
- Optimization: Constant folding, dead code elimination
- Debugging: Source line mapping, step debugger