Compare commits
20 Commits
main
..
49a1c41905
| Author | SHA1 | Date | |
|---|---|---|---|
| 49a1c41905 | |||
| 323462f13d | |||
| 1f1405391c | |||
| dd1a3468dd | |||
| 95d1496e5c | |||
| 7108402b13 | |||
| 61987d94f8 | |||
| 3046d2be62 | |||
| e8c10266ba | |||
| fa15b3c01d | |||
| 9e2d6057a7 | |||
| 7f6465437b | |||
| e322068640 | |||
| 1cf0104ae3 | |||
| cb4ec28be3 | |||
| 2fc5e98791 | |||
| c306074c07 | |||
| 3be81145da | |||
| 2089d28529 | |||
| 17fa158db4 |
@@ -28,14 +28,12 @@ A modern, C++-style scripting language designed for ease of use and powerful fun
|
|||||||
- Logical: `&&`, `||`, `!`
|
- Logical: `&&`, `||`, `!`
|
||||||
- Compound: `+=`, `-=`, `*=`, `/=`, `%=`
|
- Compound: `+=`, `-=`, `*=`, `/=`, `%=`
|
||||||
- Increment/Decrement: `++`, `--`
|
- Increment/Decrement: `++`, `--`
|
||||||
- Ternary: `condition ? true_value : false_value`
|
|
||||||
|
|
||||||
### Built-in Functions
|
### Built-in Functions
|
||||||
- **Mathematical**: `abs`, `sqrt`, `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `atan2`, `pow`, `log`, `log10`, `exp`, `floor`, `ceil`, `round`
|
- **Mathematical**: `abs`, `sqrt`, `sin`, `cos`, `tan`, `pow`, `log`, `floor`, `ceil`, `round`
|
||||||
- **String**: `strcmp`, `strcpy`, `strcat`, `strlen`, `strchr`, `strstr`, `tolower`, `toupper`, `sizeof`
|
- **String**: `strcmp`, `strcpy`, `strcat`, `sizeof`
|
||||||
- **Array**: `arrlen`, `memcpy`, `memcmp`, `malloc`, `push`, `pop`, `insert`, `remove`
|
- **Array**: `arrlen`, `memcpy`, `memcmp`, `malloc`
|
||||||
- **File IO**: `fopen`, `fclose`, `fread`, `fwrite`, `fgets`, `fputs`
|
- **Utility**: `echo`, `input`, `time`, `random`, `exit`, `assert`
|
||||||
- **System**: `echo`, `input`, `time`, `random`, `exit`, `assert`, `system`, `getenv`, `sleep`
|
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
+102
@@ -0,0 +1,102 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Oraset Debian Package Builder
|
||||||
|
# This script packages Oraset into a .deb file for Debian/Ubuntu
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
PACKAGE_NAME="oraset"
|
||||||
|
VERSION="1.0.0"
|
||||||
|
ARCH="all"
|
||||||
|
MAINTAINER="Oraset Developer"
|
||||||
|
DESCRIPTION="A simple cross-platform programming language"
|
||||||
|
LICENSE="GPL-3.0"
|
||||||
|
|
||||||
|
# Get the directory where the script is located
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
cd "${SCRIPT_DIR}"
|
||||||
|
|
||||||
|
# Build directory
|
||||||
|
BUILD_DIR="orasetdeb"
|
||||||
|
PACKAGE_DIR="${BUILD_DIR}/${PACKAGE_NAME}_${VERSION}_${ARCH}"
|
||||||
|
|
||||||
|
echo "=== Oraset Debian Package Builder ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Clean previous build
|
||||||
|
echo "[1/6] Cleaning previous build..."
|
||||||
|
rm -rf ${BUILD_DIR}
|
||||||
|
mkdir -p ${PACKAGE_DIR}
|
||||||
|
|
||||||
|
# Install PyInstaller if not present
|
||||||
|
echo "[2/6] Checking PyInstaller..."
|
||||||
|
if ! command -v pyinstaller &> /dev/null; then
|
||||||
|
echo "Installing PyInstaller..."
|
||||||
|
pip install --break-system-packages pyinstaller
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create binary with PyInstaller
|
||||||
|
echo "[3/6] Building binary with PyInstaller..."
|
||||||
|
pyinstaller --onefile --name oraset oraset.py
|
||||||
|
|
||||||
|
# Copy binary to package directory
|
||||||
|
echo "[4/6] Copying files..."
|
||||||
|
mkdir -p ${PACKAGE_DIR}/usr/bin
|
||||||
|
cp dist/oraset ${PACKAGE_DIR}/usr/bin/
|
||||||
|
|
||||||
|
# Create DEBIAN directory and control file
|
||||||
|
echo "[5/6] Creating package metadata..."
|
||||||
|
mkdir -p ${PACKAGE_DIR}/DEBIAN
|
||||||
|
|
||||||
|
cat > ${PACKAGE_DIR}/DEBIAN/control << EOF
|
||||||
|
Package: ${PACKAGE_NAME}
|
||||||
|
Version: ${VERSION}
|
||||||
|
Section: interpreters
|
||||||
|
Priority: optional
|
||||||
|
Architecture: ${ARCH}
|
||||||
|
Depends: python3
|
||||||
|
Maintainer: ${MAINTAINER}
|
||||||
|
Description: ${DESCRIPTION}
|
||||||
|
A simple cross-platform programming language written in Python.
|
||||||
|
Supports Windows and Linux, with features like variables,
|
||||||
|
functions, classes, conditional statements, loops, and more.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Create copyright file
|
||||||
|
mkdir -p ${PACKAGE_DIR}/usr/share/doc/${PACKAGE_NAME}
|
||||||
|
cat > ${PACKAGE_DIR}/usr/share/doc/${PACKAGE_NAME}/copyright << EOF
|
||||||
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: ${PACKAGE_NAME}
|
||||||
|
Upstream-Contact: ${MAINTAINER}
|
||||||
|
Source: https://github.com/oraset/oraset
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: ${LICENSE}
|
||||||
|
License: GPL-3.0
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License.
|
||||||
|
.
|
||||||
|
On a Debian system, you can find the complete text of the GPL-3.0
|
||||||
|
license in /usr/share/common-licenses/GPL-3.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Build the .deb package
|
||||||
|
echo "[6/6] Building .deb package..."
|
||||||
|
dpkg-deb --build ${PACKAGE_DIR}
|
||||||
|
|
||||||
|
# Move package to current directory
|
||||||
|
mv ${PACKAGE_DIR}.deb ${BUILD_DIR}/
|
||||||
|
|
||||||
|
# Clean up PyInstaller build files
|
||||||
|
rm -rf build dist
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Build Complete ==="
|
||||||
|
echo "Package created: ${BUILD_DIR}/${PACKAGE_NAME}_${VERSION}_${ARCH}.deb"
|
||||||
|
echo ""
|
||||||
|
echo "To install the package, run:"
|
||||||
|
echo " sudo dpkg -i ${BUILD_DIR}/${PACKAGE_NAME}_${VERSION}_${ARCH}.deb"
|
||||||
|
echo ""
|
||||||
|
echo "To uninstall the package, run:"
|
||||||
|
echo " sudo dpkg -r ${PACKAGE_NAME}"
|
||||||
+2
-280
@@ -92,8 +92,7 @@ typedef enum {
|
|||||||
TOKEN_CATCH,
|
TOKEN_CATCH,
|
||||||
TOKEN_THROW,
|
TOKEN_THROW,
|
||||||
TOKEN_ASTERISK,
|
TOKEN_ASTERISK,
|
||||||
TOKEN_LABEL,
|
TOKEN_LABEL
|
||||||
TOKEN_QUESTION
|
|
||||||
} OraTokenType;
|
} OraTokenType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -410,7 +409,6 @@ void tokenize(const char* source) {
|
|||||||
case '!': add_token(TOKEN_NOT, "!"); break;
|
case '!': add_token(TOKEN_NOT, "!"); break;
|
||||||
case ':': add_token(TOKEN_COLON, ":"); break;
|
case ':': add_token(TOKEN_COLON, ":"); break;
|
||||||
case '.': add_token(TOKEN_DOT, "."); break;
|
case '.': add_token(TOKEN_DOT, "."); break;
|
||||||
case '?': add_token(TOKEN_QUESTION, "?"); break;
|
|
||||||
default: error("Unknown character: '%c'", *p);
|
default: error("Unknown character: '%c'", *p);
|
||||||
}
|
}
|
||||||
p++;
|
p++;
|
||||||
@@ -788,271 +786,6 @@ double parse_call(const char* func_name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} else if (strcmp(func_name, "fopen") == 0) {
|
|
||||||
const char* filename = get_string_value();
|
|
||||||
consume(TOKEN_COMMA, "Expected ','");
|
|
||||||
const char* mode = get_string_value();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
for (int i = 0; i < var_count; i++) {
|
|
||||||
if (strcmp(vars[i].name, "__tmp_file_result") == 0) {
|
|
||||||
FILE* fp = fopen(filename, mode);
|
|
||||||
vars[i].value.num_value = (double)(intptr_t)fp;
|
|
||||||
vars[i].value.type = VAL_NUMBER;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
strncpy(vars[var_count].name, "__tmp_file_result", 63);
|
|
||||||
FILE* fp = fopen(filename, mode);
|
|
||||||
vars[var_count].value.num_value = (double)(intptr_t)fp;
|
|
||||||
vars[var_count].value.type = VAL_NUMBER;
|
|
||||||
var_count++;
|
|
||||||
return 0;
|
|
||||||
} else if (strcmp(func_name, "fclose") == 0) {
|
|
||||||
double fp_val = evaluate();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
FILE* fp = (FILE*)(intptr_t)fp_val;
|
|
||||||
return (double)fclose(fp);
|
|
||||||
} else if (strcmp(func_name, "fgets") == 0) {
|
|
||||||
double fp_val = evaluate();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
FILE* fp = (FILE*)(intptr_t)fp_val;
|
|
||||||
char buf[MAX_STRING];
|
|
||||||
if (fgets(buf, MAX_STRING, fp)) {
|
|
||||||
for (int i = 0; i < var_count; i++) {
|
|
||||||
if (strcmp(vars[i].name, "__tmp_str_result") == 0) {
|
|
||||||
strncpy(vars[i].value.str_value, buf, MAX_STRING - 1);
|
|
||||||
vars[i].value.str_value[MAX_STRING - 1] = '\0';
|
|
||||||
vars[i].value.type = VAL_STRING;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
strncpy(vars[var_count].name, "__tmp_str_result", 63);
|
|
||||||
strncpy(vars[var_count].value.str_value, buf, MAX_STRING - 1);
|
|
||||||
vars[var_count].value.str_value[MAX_STRING - 1] = '\0';
|
|
||||||
vars[var_count].value.type = VAL_STRING;
|
|
||||||
var_count++;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
} else if (strcmp(func_name, "fputs") == 0) {
|
|
||||||
const char* str = get_string_value();
|
|
||||||
consume(TOKEN_COMMA, "Expected ','");
|
|
||||||
double fp_val = evaluate();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
FILE* fp = (FILE*)(intptr_t)fp_val;
|
|
||||||
return (double)fputs(str, fp);
|
|
||||||
} else if (strcmp(func_name, "fread") == 0) {
|
|
||||||
consume(TOKEN_IDENTIFIER, "Expected array variable");
|
|
||||||
const char* name = tokens[current_token - 1].value;
|
|
||||||
consume(TOKEN_COMMA, "Expected ','");
|
|
||||||
int count = (int)evaluate();
|
|
||||||
consume(TOKEN_COMMA, "Expected ','");
|
|
||||||
double fp_val = evaluate();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
FILE* fp = (FILE*)(intptr_t)fp_val;
|
|
||||||
Value* arr = find_variable(name);
|
|
||||||
if (!arr) error("Undefined variable: %s", name);
|
|
||||||
if (arr->type != VAL_ARRAY) {
|
|
||||||
arr->type = VAL_ARRAY;
|
|
||||||
arr->arr_size = 0;
|
|
||||||
}
|
|
||||||
double buf[MAX_ARRAY_SIZE];
|
|
||||||
size_t read = fread(buf, sizeof(double), count, fp);
|
|
||||||
for (int i = 0; i < read && arr->arr_size + i < MAX_ARRAY_SIZE; i++) {
|
|
||||||
arr->arr_value[arr->arr_size + i] = buf[i];
|
|
||||||
}
|
|
||||||
arr->arr_size += read;
|
|
||||||
return (double)read;
|
|
||||||
} else if (strcmp(func_name, "fwrite") == 0) {
|
|
||||||
consume(TOKEN_IDENTIFIER, "Expected array variable");
|
|
||||||
const char* name = tokens[current_token - 1].value;
|
|
||||||
consume(TOKEN_COMMA, "Expected ','");
|
|
||||||
int count = (int)evaluate();
|
|
||||||
consume(TOKEN_COMMA, "Expected ','");
|
|
||||||
double fp_val = evaluate();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
FILE* fp = (FILE*)(intptr_t)fp_val;
|
|
||||||
Value* arr = find_variable(name);
|
|
||||||
if (!arr || arr->type != VAL_ARRAY) error("Invalid array");
|
|
||||||
size_t written = fwrite(arr->arr_value, sizeof(double), count, fp);
|
|
||||||
return (double)written;
|
|
||||||
} else if (strcmp(func_name, "strlen") == 0) {
|
|
||||||
const char* str = get_string_value();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
return strlen(str);
|
|
||||||
} else if (strcmp(func_name, "strchr") == 0) {
|
|
||||||
const char* str = get_string_value();
|
|
||||||
consume(TOKEN_COMMA, "Expected ','");
|
|
||||||
double ch = evaluate();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
const char* found = strchr(str, (int)ch);
|
|
||||||
return found ? (double)(found - str) : -1;
|
|
||||||
} else if (strcmp(func_name, "strstr") == 0) {
|
|
||||||
const char* str = get_string_value();
|
|
||||||
consume(TOKEN_COMMA, "Expected ','");
|
|
||||||
const char* substr = get_string_value();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
const char* found = strstr(str, substr);
|
|
||||||
return found ? (double)(found - str) : -1;
|
|
||||||
} else if (strcmp(func_name, "tolower") == 0) {
|
|
||||||
const char* str = get_string_value();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
for (int i = 0; i < var_count; i++) {
|
|
||||||
if (strcmp(vars[i].name, "__tmp_str_result") == 0) {
|
|
||||||
strncpy(vars[i].value.str_value, str, MAX_STRING - 1);
|
|
||||||
for (int j = 0; vars[i].value.str_value[j]; j++) {
|
|
||||||
vars[i].value.str_value[j] = tolower(vars[i].value.str_value[j]);
|
|
||||||
}
|
|
||||||
vars[i].value.type = VAL_STRING;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
strncpy(vars[var_count].name, "__tmp_str_result", 63);
|
|
||||||
strncpy(vars[var_count].value.str_value, str, MAX_STRING - 1);
|
|
||||||
for (int j = 0; vars[var_count].value.str_value[j]; j++) {
|
|
||||||
vars[var_count].value.str_value[j] = tolower(vars[var_count].value.str_value[j]);
|
|
||||||
}
|
|
||||||
vars[var_count].value.type = VAL_STRING;
|
|
||||||
var_count++;
|
|
||||||
return 0;
|
|
||||||
} else if (strcmp(func_name, "toupper") == 0) {
|
|
||||||
const char* str = get_string_value();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
for (int i = 0; i < var_count; i++) {
|
|
||||||
if (strcmp(vars[i].name, "__tmp_str_result") == 0) {
|
|
||||||
strncpy(vars[i].value.str_value, str, MAX_STRING - 1);
|
|
||||||
for (int j = 0; vars[i].value.str_value[j]; j++) {
|
|
||||||
vars[i].value.str_value[j] = toupper(vars[i].value.str_value[j]);
|
|
||||||
}
|
|
||||||
vars[i].value.type = VAL_STRING;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
strncpy(vars[var_count].name, "__tmp_str_result", 63);
|
|
||||||
strncpy(vars[var_count].value.str_value, str, MAX_STRING - 1);
|
|
||||||
for (int j = 0; vars[var_count].value.str_value[j]; j++) {
|
|
||||||
vars[var_count].value.str_value[j] = toupper(vars[var_count].value.str_value[j]);
|
|
||||||
}
|
|
||||||
vars[var_count].value.type = VAL_STRING;
|
|
||||||
var_count++;
|
|
||||||
return 0;
|
|
||||||
} else if (strcmp(func_name, "asin") == 0) {
|
|
||||||
double val = evaluate();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
return asin(val);
|
|
||||||
} else if (strcmp(func_name, "acos") == 0) {
|
|
||||||
double val = evaluate();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
return acos(val);
|
|
||||||
} else if (strcmp(func_name, "atan") == 0) {
|
|
||||||
double val = evaluate();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
return atan(val);
|
|
||||||
} else if (strcmp(func_name, "atan2") == 0) {
|
|
||||||
double y = evaluate();
|
|
||||||
consume(TOKEN_COMMA, "Expected ','");
|
|
||||||
double x = evaluate();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
return atan2(y, x);
|
|
||||||
} else if (strcmp(func_name, "log10") == 0) {
|
|
||||||
double val = evaluate();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
return log10(val);
|
|
||||||
} else if (strcmp(func_name, "exp") == 0) {
|
|
||||||
double val = evaluate();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
return exp(val);
|
|
||||||
} else if (strcmp(func_name, "system") == 0) {
|
|
||||||
const char* cmd = get_string_value();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
return (double)system(cmd);
|
|
||||||
} else if (strcmp(func_name, "getenv") == 0) {
|
|
||||||
const char* name = get_string_value();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
const char* val = getenv(name);
|
|
||||||
if (val) {
|
|
||||||
for (int i = 0; i < var_count; i++) {
|
|
||||||
if (strcmp(vars[i].name, "__tmp_str_result") == 0) {
|
|
||||||
strncpy(vars[i].value.str_value, val, MAX_STRING - 1);
|
|
||||||
vars[i].value.str_value[MAX_STRING - 1] = '\0';
|
|
||||||
vars[i].value.type = VAL_STRING;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
strncpy(vars[var_count].name, "__tmp_str_result", 63);
|
|
||||||
strncpy(vars[var_count].value.str_value, val, MAX_STRING - 1);
|
|
||||||
vars[var_count].value.str_value[MAX_STRING - 1] = '\0';
|
|
||||||
vars[var_count].value.type = VAL_STRING;
|
|
||||||
var_count++;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
} else if (strcmp(func_name, "sleep") == 0) {
|
|
||||||
double seconds = evaluate();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
#ifdef OS_WINDOWS
|
|
||||||
Sleep((DWORD)(seconds * 1000));
|
|
||||||
#else
|
|
||||||
sleep((unsigned int)seconds);
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
} else if (strcmp(func_name, "push") == 0) {
|
|
||||||
consume(TOKEN_IDENTIFIER, "Expected array variable");
|
|
||||||
const char* name = tokens[current_token - 1].value;
|
|
||||||
consume(TOKEN_COMMA, "Expected ','");
|
|
||||||
double val = evaluate();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
Value* arr = find_variable(name);
|
|
||||||
if (!arr) error("Undefined variable: %s", name);
|
|
||||||
if (arr->type != VAL_ARRAY) {
|
|
||||||
arr->type = VAL_ARRAY;
|
|
||||||
arr->arr_size = 0;
|
|
||||||
}
|
|
||||||
if (arr->arr_size >= MAX_ARRAY_SIZE) {
|
|
||||||
error("Array size exceeds maximum (%d)", MAX_ARRAY_SIZE);
|
|
||||||
}
|
|
||||||
arr->arr_value[arr->arr_size++] = val;
|
|
||||||
return 0;
|
|
||||||
} else if (strcmp(func_name, "pop") == 0) {
|
|
||||||
consume(TOKEN_IDENTIFIER, "Expected array variable");
|
|
||||||
const char* name = tokens[current_token - 1].value;
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
Value* arr = find_variable(name);
|
|
||||||
if (!arr || arr->type != VAL_ARRAY || arr->arr_size == 0) {
|
|
||||||
error("Cannot pop from empty array");
|
|
||||||
}
|
|
||||||
return arr->arr_value[--arr->arr_size];
|
|
||||||
} else if (strcmp(func_name, "insert") == 0) {
|
|
||||||
consume(TOKEN_IDENTIFIER, "Expected array variable");
|
|
||||||
const char* name = tokens[current_token - 1].value;
|
|
||||||
consume(TOKEN_COMMA, "Expected ','");
|
|
||||||
int index = (int)evaluate();
|
|
||||||
consume(TOKEN_COMMA, "Expected ','");
|
|
||||||
double val = evaluate();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
Value* arr = find_variable(name);
|
|
||||||
if (!arr || arr->type != VAL_ARRAY) error("Invalid array");
|
|
||||||
if (index < 0 || index > arr->arr_size) error("Array index out of bounds");
|
|
||||||
if (arr->arr_size >= MAX_ARRAY_SIZE) error("Array full");
|
|
||||||
for (int i = arr->arr_size; i > index; i--) {
|
|
||||||
arr->arr_value[i] = arr->arr_value[i - 1];
|
|
||||||
}
|
|
||||||
arr->arr_value[index] = val;
|
|
||||||
arr->arr_size++;
|
|
||||||
return 0;
|
|
||||||
} else if (strcmp(func_name, "remove") == 0) {
|
|
||||||
consume(TOKEN_IDENTIFIER, "Expected array variable");
|
|
||||||
const char* name = tokens[current_token - 1].value;
|
|
||||||
consume(TOKEN_COMMA, "Expected ','");
|
|
||||||
int index = (int)evaluate();
|
|
||||||
consume(TOKEN_RPAREN, "Expected ')'");
|
|
||||||
Value* arr = find_variable(name);
|
|
||||||
if (!arr || arr->type != VAL_ARRAY) error("Invalid array");
|
|
||||||
if (index < 0 || index >= arr->arr_size) error("Array index out of bounds");
|
|
||||||
double result = arr->arr_value[index];
|
|
||||||
for (int i = index; i < arr->arr_size - 1; i++) {
|
|
||||||
arr->arr_value[i] = arr->arr_value[i + 1];
|
|
||||||
}
|
|
||||||
arr->arr_size--;
|
|
||||||
return result;
|
|
||||||
} else {
|
} else {
|
||||||
int func_idx = find_function(func_name);
|
int func_idx = find_function(func_name);
|
||||||
if (func_idx >= 0) {
|
if (func_idx >= 0) {
|
||||||
@@ -1269,19 +1002,8 @@ double parse_logic_or() {
|
|||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
double parse_ternary() {
|
|
||||||
double cond = parse_logic_or();
|
|
||||||
if (match(TOKEN_QUESTION)) {
|
|
||||||
double true_val = parse_ternary();
|
|
||||||
consume(TOKEN_COLON, "Expected ':' in ternary expression");
|
|
||||||
double false_val = parse_ternary();
|
|
||||||
return cond != 0 ? true_val : false_val;
|
|
||||||
}
|
|
||||||
return cond;
|
|
||||||
}
|
|
||||||
|
|
||||||
double evaluate() {
|
double evaluate() {
|
||||||
return parse_ternary();
|
return parse_logic_or();
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute_print() {
|
void execute_print() {
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Hello, Oraset!
|
||||||
|
This is a test file.
|
||||||
@@ -1 +0,0 @@
|
|||||||
Hello World
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
echo("=== 新功能测试 ===");
|
|
||||||
|
|
||||||
echo("");
|
|
||||||
echo("=== 三元运算符测试 ===");
|
|
||||||
let a = 10;
|
|
||||||
let b = 20;
|
|
||||||
let max = (a > b) ? a : b;
|
|
||||||
echo("max =", max);
|
|
||||||
let min = (a < b) ? a : b;
|
|
||||||
echo("min =", min);
|
|
||||||
|
|
||||||
echo("");
|
|
||||||
echo("=== 文件IO测试 ===");
|
|
||||||
fopen("test_io.txt", "w");
|
|
||||||
fputs("Hello World\n", __tmp_file_result);
|
|
||||||
fclose(__tmp_file_result);
|
|
||||||
|
|
||||||
fopen("test_io.txt", "r");
|
|
||||||
fgets(__tmp_file_result);
|
|
||||||
echo("读取第一行:", __tmp_str_result);
|
|
||||||
fclose(__tmp_file_result);
|
|
||||||
|
|
||||||
echo("");
|
|
||||||
echo("=== 字符串函数测试 ===");
|
|
||||||
let s = "Hello World";
|
|
||||||
echo("strlen(s) =", strlen(s));
|
|
||||||
echo("strchr(s, 'W') =", strchr(s, 87));
|
|
||||||
echo("strstr(s, 'World') =", strstr(s, "World"));
|
|
||||||
|
|
||||||
toupper(s);
|
|
||||||
echo("toupper:", __tmp_str_result);
|
|
||||||
|
|
||||||
tolower(__tmp_str_result);
|
|
||||||
echo("tolower:", __tmp_str_result);
|
|
||||||
|
|
||||||
echo("");
|
|
||||||
echo("=== 数学函数测试 ===");
|
|
||||||
echo("sin(0) =", sin(0));
|
|
||||||
echo("cos(0) =", cos(0));
|
|
||||||
echo("asin(0) =", asin(0));
|
|
||||||
echo("acos(1) =", acos(1));
|
|
||||||
echo("atan(0) =", atan(0));
|
|
||||||
echo("atan2(1, 0) =", atan2(1, 0));
|
|
||||||
echo("log10(100) =", log10(100));
|
|
||||||
echo("exp(1) =", exp(1));
|
|
||||||
|
|
||||||
echo("");
|
|
||||||
echo("=== 数组操作测试 ===");
|
|
||||||
let arr = [1, 2, 3];
|
|
||||||
echo("初始数组:", arr);
|
|
||||||
|
|
||||||
push(arr, 4);
|
|
||||||
echo("push后:", arr);
|
|
||||||
|
|
||||||
let popped = pop(arr);
|
|
||||||
echo("pop出:", popped);
|
|
||||||
echo("pop后:", arr);
|
|
||||||
|
|
||||||
insert(arr, 1, 99);
|
|
||||||
echo("insert后:", arr);
|
|
||||||
|
|
||||||
let removed = remove(arr, 1);
|
|
||||||
echo("remove出:", removed);
|
|
||||||
echo("remove后:", arr);
|
|
||||||
|
|
||||||
echo("");
|
|
||||||
echo("=== 系统函数测试 ===");
|
|
||||||
getenv("PATH");
|
|
||||||
echo("PATH长度:", strlen(__tmp_str_result));
|
|
||||||
|
|
||||||
echo("");
|
|
||||||
echo("所有新功能测试完成!");
|
|
||||||
@@ -34,11 +34,13 @@
|
|||||||
<h2>最新版本:B-5</h2>
|
<h2>最新版本:B-5</h2>
|
||||||
<p class="version-note">构建日期: 2026.7.22 | 全新升级版本</p>
|
<p class="version-note">构建日期: 2026.7.22 | 全新升级版本</p>
|
||||||
|
|
||||||
<h2>Windows <span class="version-badge">B-5</span></h2>
|
<h2>源码下载</h2>
|
||||||
<p><strong>EXE 可执行文件</strong></p>
|
<p>如果您想从源码编译 Oraset:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="download/exe/Oraset-B-5.exe">Oraset-B-5.exe</a></li>
|
<li><a href="download/source/Oraset-B5-source.tar.gz">Oraset-B5-source.tar.gz</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<p>编译方法:</p>
|
||||||
|
<pre>make</pre>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -1,26 +0,0 @@
|
|||||||
CC = gcc
|
|
||||||
CFLAGS = -Wall -Wextra -O2 -std=c11
|
|
||||||
BINDIR = bin
|
|
||||||
|
|
||||||
TARGET = $(BINDIR)/oraset
|
|
||||||
|
|
||||||
SRCS = src/main.c
|
|
||||||
|
|
||||||
all: $(TARGET)
|
|
||||||
|
|
||||||
$(TARGET): $(SRCS)
|
|
||||||
@mkdir -p $(BINDIR)
|
|
||||||
$(CC) $(CFLAGS) -o $(TARGET) $(SRCS)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(TARGET)
|
|
||||||
rm -rf $(BINDIR)
|
|
||||||
|
|
||||||
pkg: all
|
|
||||||
rm -rf pkg-root
|
|
||||||
mkdir -p pkg-root/usr/local/bin
|
|
||||||
cp bin/oraset pkg-root/usr/local/bin/oraset
|
|
||||||
chmod +x pkg-root/usr/local/bin/oraset
|
|
||||||
pkgbuild --root pkg-root --identifier com.oraset.lang --version B-5 --install-location / Oraset-B5.pkg
|
|
||||||
|
|
||||||
.PHONY: all clean pkg
|
|
||||||
File diff suppressed because it is too large
Load Diff
+13
-30
@@ -33,46 +33,29 @@
|
|||||||
<p>Version: <strong>B-5</strong></p>
|
<p>Version: <strong>B-5</strong></p>
|
||||||
|
|
||||||
<h2>关于</h2>
|
<h2>关于</h2>
|
||||||
<p>Oraset 是一个现代化的 C++ 风格脚本语言,功能强大且易于使用。</p>
|
<p>Oraset 是一个简洁高效的解释型编程语言,专为简单任务和脚本编写设计。</p>
|
||||||
|
|
||||||
<h2>特性</h2>
|
<h2>特性</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>C++ 风格语法设计</li>
|
<li>简洁直观的语法</li>
|
||||||
<li>轻量级解释器(纯 C 实现)</li>
|
<li>轻量级解释器</li>
|
||||||
<li>变量定义(let 关键字)</li>
|
<li>变量和表达式支持</li>
|
||||||
<li>数组支持(创建、访问、修改)</li>
|
<li>条件语句和循环</li>
|
||||||
<li>自定义函数(proc 关键字)</li>
|
<li>灵活的输出控制(print 函数)</li>
|
||||||
<li>条件语句(if-else)</li>
|
<li>数组支持</li>
|
||||||
<li>循环语句(while、for、do-while)</li>
|
<li>自定义函数</li>
|
||||||
<li>switch-case 语句</li>
|
|
||||||
<li>goto 语句和标签</li>
|
|
||||||
<li>break 和 continue</li>
|
|
||||||
<li>位运算符(&、|、^、~、<<、>>)</li>
|
|
||||||
<li>复合赋值运算符(+=、-=、*=、/=、%=)</li>
|
|
||||||
<li>自增自减运算符(++、--)</li>
|
|
||||||
<li>结构体(struct)</li>
|
|
||||||
<li>枚举(enum)</li>
|
|
||||||
<li>类型别名(typedef)</li>
|
|
||||||
<li>丰富的内置函数(数学、字符串、数组)</li>
|
<li>丰富的内置函数(数学、字符串、数组)</li>
|
||||||
|
<li>复合赋值和自增自减运算符</li>
|
||||||
<li>REPL 交互模式</li>
|
<li>REPL 交互模式</li>
|
||||||
<li>跨平台支持(Windows、macOS、Linux)</li>
|
<li>跨平台支持(Windows、macOS、Linux)</li>
|
||||||
|
<li>自动更新功能(oraset -u)</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2>快速开始</h2>
|
<h2>快速开始</h2>
|
||||||
<pre>// hello.ora
|
<pre>// hello.ora
|
||||||
echo("Hello, World!");
|
print("Hello, World!");
|
||||||
let x = 42;
|
var x = 42;
|
||||||
echo("The value is:", x);
|
print("The value is:", x);</pre>
|
||||||
|
|
||||||
// 数组
|
|
||||||
let arr = [1, 2, 3];
|
|
||||||
echo(arr[0]);
|
|
||||||
|
|
||||||
// 函数
|
|
||||||
proc add(a, b) {
|
|
||||||
return a + b;
|
|
||||||
}
|
|
||||||
echo(add(10, 20));</pre>
|
|
||||||
|
|
||||||
<p>运行:<code>oraset hello.ora</code></p>
|
<p>运行:<code>oraset hello.ora</code></p>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user