Skip to content
Merged
Show file tree
Hide file tree
Changes from 60 commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
b62e9f7
1
russo-2025 May 28, 2025
a540bf6
Merge branch 'master' into replace-panics
russo-2025 May 28, 2025
d35cb3f
wip
russo-2025 May 30, 2025
1fc145d
Update README.RU.md
russo-2025 Jun 28, 2025
f5c7a1d
update v version
russo-2025 Jun 28, 2025
fd5c2a8
update version command
russo-2025 Jun 28, 2025
d6ab4da
Update README.RU.md
russo-2025 Jun 28, 2025
9fb1ee0
Update CHANGELOG.md
russo-2025 Sep 15, 2025
938e842
Fix None literal in object variable | update v version
russo-2025 Sep 15, 2025
e4bd062
Update V setup action to v1.4 in workflows
russo-2025 Sep 15, 2025
cfe2f4d
add sexlab sources
russo-2025 Sep 16, 2025
10b30fe
small rename file iequip_test -> proj_iequip_test
russo-2025 Sep 16, 2025
dce7609
add test project sexlab
russo-2025 Sep 16, 2025
5358af9
Move iEquip scripts to iEquipSources directory
russo-2025 Sep 16, 2025
94c111c
Add MantellaSpellSources scripts and assets
russo-2025 Sep 16, 2025
5d55ff0
Add OStim Papyrus source scripts and license
russo-2025 Sep 16, 2025
8cdfa88
Add PapyrusUtil source scripts for testing
russo-2025 Sep 16, 2025
e2ee34c
Add ModEvent and NetImmerse script dependencies
russo-2025 Sep 16, 2025
21fe429
Rename and update iEquip test file
russo-2025 Sep 16, 2025
80f7ed7
Rename and update SexLab test function
russo-2025 Sep 16, 2025
452340d
Add Mantella spell project test
russo-2025 Sep 16, 2025
aca2b77
Add test for OStim project compilation
russo-2025 Sep 16, 2025
1a144eb
Add UIExtensionsSources scripts for testing
russo-2025 Oct 2, 2025
ed90a88
Add RaceMenu Papyrus source scripts for testing
russo-2025 Oct 2, 2025
c90b345
Add Papyrus script stubs for SKSE dependencies
russo-2025 Oct 2, 2025
82825a4
Add NiOverride and ArmorAddon Papyrus scripts
russo-2025 Oct 2, 2025
a9e6629
Add MCM Helper source scripts for testing
russo-2025 Oct 2, 2025
2cab96c
Add MasterOfDisguise source scripts and docs
russo-2025 Oct 2, 2025
dd10a73
Add LibTurtleClub source files and license
russo-2025 Oct 2, 2025
8b609ec
Add LibFireSources test module
russo-2025 Oct 2, 2025
5427ecf
Add LibMathf.psc with math utility functions
russo-2025 Oct 2, 2025
057c4c1
Add JContainers Papyrus API source files
russo-2025 Oct 2, 2025
ae82272
Remove iEquipSources test scripts
russo-2025 Oct 2, 2025
6315c69
Add ConsoleUtil sources for testing
russo-2025 Oct 2, 2025
602cc82
Consolidate project test files into projects_test.v
russo-2025 Oct 2, 2025
f760982
Add debug print for compile command execution
russo-2025 Oct 3, 2025
11ee38c
wip
russo-2025 Oct 3, 2025
73c9aca
wip
russo-2025 Oct 8, 2025
9e2feab
Merge branch 'replace-panics' of https://github.com/russo-2025/papyru…
russo-2025 Oct 24, 2025
a6eaf36
wip
russo-2025 Nov 13, 2025
951f2af
Add OSA Papyrus source scripts for testing
russo-2025 Nov 15, 2025
5843c11
Remove unused SexLab and iEquip test sources
russo-2025 Nov 15, 2025
f896381
Add OStimNG Papyrus source scripts for testing
russo-2025 Nov 25, 2025
f0b03b3
Refactor SkyUI SDK sources by version and add v5.2
russo-2025 Nov 25, 2025
214def3
Add Camera.psc and update Game.psc for camera functions
russo-2025 Nov 25, 2025
18c24b0
Update test projects for multiple SkyUI SDK versions
russo-2025 Nov 25, 2025
2294198
Remove debug output from ast_test.v
russo-2025 Dec 24, 2025
f10557a
Print header dirs only outside test builds
russo-2025 Dec 24, 2025
0f7bcda
Update V compiler version and improve temp var handling
russo-2025 Dec 24, 2025
516d606
Refactor test project setup with helper functions
russo-2025 Dec 24, 2025
1b0c8c9
Improve test output handling and directory management
russo-2025 Dec 24, 2025
ee7f975
Set output_mode to silent in test preferences
russo-2025 Dec 24, 2025
01f6c96
Refactor test project setup with get_prefs helper
russo-2025 Dec 24, 2025
4d8d610
Refactor test project source path usage
russo-2025 Dec 24, 2025
8607cd7
Replace println with b.print and improve error output
russo-2025 Dec 25, 2025
abc7af9
Update output directory names in test functions
russo-2025 Dec 25, 2025
8bf275a
Improve type validation and error handling in checker
russo-2025 Dec 25, 2025
df02115
Add README for Original Compiler directory
russo-2025 Dec 25, 2025
7cce64a
Fix indentation in ast_test.v preferences constant
russo-2025 Dec 25, 2025
634581e
Prefix output dir with __project_test_ in get_output_dir
russo-2025 Dec 25, 2025
2807acc
Update CHANGELOG
russo-2025 Dec 26, 2025
827432b
Validate script name matches file and uniqueness
russo-2025 Mar 14, 2026
af341d3
Add AGENTS.md system prompt
russo-2025 Mar 14, 2026
98f2554
Improve cast assertion message
russo-2025 Mar 14, 2026
ea1289e
add RequiemSources
russo-2025 Mar 14, 2026
f240b69
add CampfireSources
russo-2025 Mar 14, 2026
855c1c1
Add try_cast_to_type and use safe casts
russo-2025 Mar 14, 2026
e8b8b3d
Update CHANGELOG with new features and fixes
russo-2025 Mar 14, 2026
ba94ae6
Add changelog rules for user-visible changes
russo-2025 Mar 14, 2026
1a18a02
Prevent placeholder type crashes; support comments
russo-2025 Mar 14, 2026
c44f0f0
move papyrus sources to separate repo
russo-2025 Mar 14, 2026
b37fbb2
Update checkout action to v4; enable submodules
russo-2025 Mar 14, 2026
3fddff2
Update header_dir path and translate comments
russo-2025 Mar 14, 2026
90f54ba
Update test source path for selective headers
russo-2025 Mar 14, 2026
9ead6b0
Fix path to PSC test file in selective headers test
russo-2025 Mar 14, 2026
c095dbd
Remove Campfire project and update Requiem deps
russo-2025 Mar 15, 2026
b99fa5b
Handle alternate test source/header paths
russo-2025 Mar 15, 2026
d56a6b9
update test sources submodule
russo-2025 Mar 15, 2026
80d2e28
header image to READMEs
russo-2025 Mar 15, 2026
9c151cb
Enable debug (-g) in V build step
russo-2025 Mar 15, 2026
2201a00
Add v0.0.4 changelog and improve errors
russo-2025 Mar 15, 2026
6fb7136
Add -g flag to build command in READMEs
russo-2025 Mar 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- name: Install V
uses: vlang/setup-v@v1
uses: vlang/setup-v@v1.4
with:
version: weekly.2025.09
version: weekly.2025.48

- name: Checkout ${{ github.event.repository.name }}
uses: actions/checkout@v2
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/manual-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ jobs:
uses: actions/checkout@v2

- name: Install V
uses: vlang/setup-v@v1
uses: vlang/setup-v@v1.4
with:
version: weekly.2025.09
version: weekly.2025.48

- name: Build Project
run: v -prod -gc none -o "bin/papyrus" compiler.v
Expand Down
28 changes: 27 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@
## Next release
## Next Release

### Improvements

- **Improved Error Handling**
- All panics replaced with more informative alternatives for better debugging.

- **Developer Experience Enhancements**
- Added bug report issue template to streamline problem reporting.
- Added `version` command to display current compiler version.
- Updated supported V compiler version.
- TODO: Update help command documentation.
- добавлен compile-time каст значений-литералов (int "123" -> 123) для параметров по умолчанию и значений в объявлении свойства
```
int Property MyPropAutoCast = \"123\" Auto`
```
```
Int Function MyFunc(int n1, int n2 = \"12\")
return n1
EndFunction"
```
- исправлены none значения у property и параметров по умолчанию в функцях
- добавлены проверки отсутствующих скриптов в некоторых местах
- добавлены проверки родителей у скриптов
- исправлена проверка аргумента функции в состоянии с параметром по умолчанию
- добавлена проверка параметра по умолчанию

...

## V 0.0.3
Expand Down
7 changes: 5 additions & 2 deletions README.RU.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Компилятор скриптового языка Papyrus с открытым исходным кодом. На данный момент компилятор поддерживает только Skyrim (тестировался на Skyrim SE/AE).

[![Discord Chat](https://img.shields.io/discord/1377359857220321416?label=Discord&logo=Discord)](https://discord.gg/JqQZXAXvPT)

Компилятор был создан для следующих целей:
1. **Понимание языков программирования:** Проект разработан для того, чтобы глубже понять, как работают языки программирования.
2. **Эксперименты с языком V:** Использует язык программирования V для реализации.
Expand Down Expand Up @@ -29,6 +31,7 @@ papyrus <command> [arguments]
```

### Команды:
- `version`: Выводит версию компилятора и некоторую дополнительную информацию о билде.
- `compile`: Компилирует файлы с расширением `.psc` в бинарный формат `.pex`.
- `read`: Читает и дизассемблирует файл с расширением `.pex`, выводя его содержимое в человекочитаемом формате в консоль.
- `disassembly`: Читает и дизассемблирует файл с расширением `.pex`, сохраняя содержимое в человекочитаемом формате в текстовый файл.
Expand All @@ -45,7 +48,7 @@ papyrus <command> [arguments]
- `-silent`: Отключает вывод сообщений об ошибках в консоль.
- `-original`: Использует оригинальный компилятор Papyrus для компиляции.
- `-stats`: Сохраняет статистику по скомпилированным файлам в .md файлы (количество вызовов функций, наследований, файлов).
- `-check`: Проверяет синтаксис .psc файлов без генерации .pex файлов.
- `-check`: Проверяет синтаксис .psc файлов, но не создает .pex файлы.
- `-verbose`: ...

### Примеры использования
Expand Down Expand Up @@ -125,7 +128,7 @@ Function EquipItem(Form akItem, bool abPreventRemoval = false, bool abSilent = f
## Сборка

### Требования:
- [V compiler f3d2eb1 (weekly.2025.09)](https://github.com/vlang/v/releases/tag/weekly.2025.09)
- [V compiler d0dc13e (weekly.2025.48)](https://github.com/vlang/v/releases/tag/weekly.2025.48)

```bash
v -o "bin\papyrus.exe" -prod -gc none compiler.v
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

An open-source compiler for the Papyrus scripting language. Currently, the compiler only supports Skyrim (tested on Skyrim SE/AE).

[![Discord Chat](https://img.shields.io/discord/1377359857220321416?label=Discord&logo=Discord)](https://discord.gg/JqQZXAXvPT)

The compiler was created for the following purposes:
1. **Understanding Programming Languages:** The project is designed to gain a deeper understanding of how programming languages work.
2. **Experimenting with the V Language:** It uses the V programming language for implementation.
Expand Down Expand Up @@ -125,7 +127,7 @@ Scripts from the directory specified by the `-h "..."` argument will NOT be comp
## Building

### Requirements:
- [V compiler f3d2eb1 (weekly.2025.09)](https://github.com/vlang/v/releases/tag/weekly.2025.09)
- [V compiler d0dc13e (weekly.2025.48)](https://github.com/vlang/v/releases/tag/weekly.2025.48)

```bash
v -o "bin\papyrus.exe" -prod -gc none compiler.v
Expand Down
3 changes: 3 additions & 0 deletions bin/Original Compiler/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Original Compiler Files

This directory contains the original Papyrus compiler files from the Creation Kit.
22 changes: 19 additions & 3 deletions compiler.v
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,26 @@ import json
import builder
import pref
import pex
import papyrus.util

//#flag -lucrtd

fn main() {
prefs := pref.parse_args()

mut sw := time.new_stopwatch()
sw.start()

match prefs.mode {
.version {
info := util.collect_info()
println("Version: ${info.version}")
println("Commit: ${info.git_commit}")
println("Build date: ${info.build_date}")
println("Build type: ${info.build_type}")
println("Repository: https://github.com/russo-2025/papyrus-compiler")
exit(0)
}
.compile {
builder.compile(prefs)
}
Expand All @@ -27,12 +37,18 @@ fn main() {
.disassembly {
println("disassembly file: `${prefs.paths[0]}` ")
pex_file := pex.read_from_file(prefs.paths[0])
os.write_file(prefs.paths[0] + ".txt", pex_file.str()) or { panic(err) }
output_file_name := prefs.paths[0] + ".txt"
os.write_file(output_file_name, pex_file.str()) or {
util.fatal_error("failed to write file ${output_file_name}; ${err}")
}
}
.create_dump {
dump_objects := pex.create_dump_from_pex_dir(prefs.paths[0])
json_data := json.encode_pretty(dump_objects)
os.write_file(os.real_path("dump.json"), json_data) or { panic(err) }
output_file_name := os.real_path("dump.json")
os.write_file(output_file_name, json_data) or {
util.fatal_error("failed to write file ${output_file_name}; ${err}")
}
}
.help {
pref.print_help_info()
Expand Down
14 changes: 8 additions & 6 deletions modules/builder/builder.v
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import pref
import papyrus.ast
import papyrus.checker
import gen.gen_pex
import papyrus.util

const cache_path = os.real_path('./.papyrus')
const compiler_exe_path = os.real_path('./Original Compiler/PapyrusCompiler.exe')
Expand Down Expand Up @@ -64,7 +65,7 @@ pub fn (mut b Builder) run() bool {

b.pref.header_dirs = b.pref.header_dirs.reverse()

println("used header dirs ${b.pref.header_dirs}")
b.print("used header dirs ${b.pref.header_dirs}")

b.files, b.files_names = find_all_src_files(b.pref.paths)

Expand Down Expand Up @@ -141,11 +142,11 @@ fn (mut b Builder) start_timer(name string) {
fn (mut b Builder) print_timer(name string) {
if sw := b.timers[name] {
time_ms := f32(sw.elapsed().microseconds()) / 1000
b.print('$name: $time_ms ms')
b.print('${name}: ${time_ms} ms')
b.timers.delete(name)
}
else {
panic('invalid timer')
util.compiler_error(msg: "failed to find timer", phase: "builder", prefs: b.pref, file: @FILE, func: @FN, line: @LINE)
}
}

Expand All @@ -167,8 +168,7 @@ fn (b Builder) print(msg string) {

@[noreturn]
fn error(msg string) {
eprintln(msg)
exit(1)
util.fatal_error(msg)
}

/*
Expand All @@ -188,7 +188,9 @@ fn (mut b Builder) register_info_from_dump(dump_obj &pex.DumpObject) {
methods: []ast.Fn{}
)

mut sym := b.table.find_type(dump_obj.name) or { panic("failed to find type") }
mut sym := b.table.find_type(dump_obj.name) or {
util.compiler_error(msg: "failed to find type", phase: "builder", prefs: b.pref, file: @FILE, func: @FN, line: @LINE)
}

for dump_method in dump_obj.methods {
if !sym.has_method(dump_method.name) {
Expand Down
20 changes: 16 additions & 4 deletions modules/builder/cache.v
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,35 @@ import os

import pref
import papyrus.ast
import papyrus.util

struct CacheFile {
pub mut:
last_mod_time i64
}

fn read_cache(path string) &CacheFile {
mut file := os.open(path) or { panic(err) }
mut file := os.open(path) or {
util.fatal_error("failed to open file: ${err}")
}

mut cache := CacheFile{}
file.read_struct(mut cache) or { panic(err) }
file.read_struct(mut cache) or {
util.fatal_error("failed to read file: ${err}")
}
file.close()
return &cache
}

fn write_cache(path string, cache &CacheFile) {
mut file := os.create(path) or { panic(err) }
file.write_struct(cache) or { panic(err) }
mut file := os.create(path) or {
util.fatal_error("failed to create file: ${err}")
}

file.write_struct(cache) or {
util.fatal_error("failed to write file: ${err}")
}

file.close()
}

Expand Down
11 changes: 7 additions & 4 deletions modules/builder/original.v
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,18 @@ fn (mut b Builder) compile_original() {

for file in b.files {
cmd := '"${compiler_exe_path}" "${file}" -quiet -i="${header_dirs}" -o="${b.pref.output_dir}" -f="${compiler_flags_path}"'

b.print("executing: `${cmd}`")

res := unsafe { os.raw_execute(cmd) }

if res.exit_code == 0 {
println('successfully - ${file}')
b.print('successfully - ${file}')
}
else {
println('failed - ${file}')
println('console output:')
println(res.output)
b.print('failed - ${file}')
b.print('console output:')
b.print(res.output)
}
}
}
21 changes: 13 additions & 8 deletions modules/builder/pex.v
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import pex
import papyrus.ast
import papyrus.parser
import papyrus.checker
import papyrus.util

@[inline]
fn (mut b Builder) compile_pex() {
Expand All @@ -20,26 +21,26 @@ fn (mut b Builder) compile_pex() {
b.start_timer('parse headers files')
b.parse_deps()
b.print_timer('parse headers files')

//fns_dump.load("FunctionsDump.json", mut b.table) or { panic(err) }

b.start_timer('check files')
mut c := checker.new_checker(b.table, b.pref)
c.check_files(mut b.parsed_files)
b.print_timer('check files')

if !os.exists(cache_path) {
os.mkdir(cache_path) or { panic(err) }
os.mkdir(cache_path) or {
util.fatal_error("failed to make dir: ${err}")
}
}

if c.errors.len != 0 {
println("failed to compile files, ${c.errors.len} errors")

$if test {
println(c.errors)
print_backtrace()
assert false, "checker.errors.len != 0"
}

exit(1)
util.fatal_error("failed to compile files, ${c.errors.len} errors")
}

if b.pref.backend == .check {
Expand Down Expand Up @@ -106,8 +107,12 @@ fn (mut b Builder) gen_to_pex_file(mut parsed_file ast.File, mut buff_bytes pex.

assert !buff_bytes.is_empty()

mut file := os.create(output_file_path) or { panic(err) }
file.write(buff_bytes.bytes) or { panic(err) }
mut file := os.create(output_file_path) or {
util.fatal_error("failed to create file: ${err}")
}
file.write(buff_bytes.bytes) or {
util.fatal_error("failed to write file: ${err}")
}
file.close()
}
}
Expand Down
17 changes: 13 additions & 4 deletions modules/builder/stats.v
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module builder
import os
import strings
import papyrus.ast
import papyrus.util

struct FnInfo {
pub mut:
Expand Down Expand Up @@ -172,7 +173,9 @@ fn (s Stats) save() {
b.writeln("| native global fns | ${s.count_native_static_fns} |")
b.writeln("| all methods | ${s.count_all_methods} |")
b.writeln("| native methods | ${s.count_native_methods}")
os.write_file("stats.md", b.str()) or { panic(err) }
os.write_file("stats.md", b.str()) or {
util.fatal_error("failed to write file: ${err}")
}

mut obj_info_arr := s.obj_info.values()
obj_info_arr.sort(a.count > b.count)
Expand All @@ -186,7 +189,9 @@ fn (s Stats) save() {
b.writeln("| ${obj_info.name} | ${obj_info.count} | ")
}

os.write_file("obj_extends_count.md", b.str()) or { panic(err) }
os.write_file("obj_extends_count.md", b.str()) or {
util.fatal_error("failed to write file: ${err}")
}

mut call_info_arr := s.call_info.values()
call_info_arr.sort(a.count > b.count)
Expand All @@ -200,7 +205,9 @@ fn (s Stats) save() {
b.writeln("| ${call_info.obj_name}.${call_info.name} | ${call_info.count} | ")
}

os.write_file("all_fns_count.md", b.str()) or { panic(err) }
os.write_file("all_fns_count.md", b.str()) or {
util.fatal_error("failed to write file: ${err}")
}

// only native
b = strings.new_builder(100)
Expand All @@ -213,5 +220,7 @@ fn (s Stats) save() {
}
}

os.write_file("native_fns_count.md", b.str()) or { panic(err) }
os.write_file("native_fns_count.md", b.str()) or {
util.fatal_error("failed to write file: ${err}")
}
}
Loading