1#![doc(
4 html_logo_url = "https://ling-lang.org/images/logo.svg",
5 html_favicon_url = "https://ling-lang.org/images/logo.svg"
6)]
7
8pub mod core;
9pub mod lexer;
10pub mod parser;
11pub mod semantic;
12pub mod borrowck;
13pub mod mir;
14pub mod codegen;
15pub mod lexicon;
16pub mod polyglot;
17pub mod gfx;
18pub mod runtime;
19pub mod diag;
20pub mod utils;
21pub mod visualize;
22pub mod astviz;
23#[cfg(not(target_arch = "wasm32"))]
24pub mod convert;
25
26#[cfg(not(target_arch = "wasm32"))]
27pub use ling_audio;
28
29pub use core::{LingCompiler, CompilerConfig, OptimizationLevel};
31pub use lexicon::{CanonicalToken, Lexicon, LexiconRegistry};
32pub use polyglot::{normalize_source, ScriptDetector};
33
34pub const VERSION: &str = env!("CARGO_PKG_VERSION");
36
37pub fn run(source: &str) -> Result<(), String> {
40 run_named(source, None, None)
41}
42
43pub fn unpack_resources(app: &str, resources: &[(&str, &[u8])]) {
50 if resources.is_empty() {
51 return;
52 }
53 let base = std::env::temp_dir().join(format!("ling-pack-{app}"));
54 for (rel, bytes) in resources {
55 let dst = base.join(rel);
56 if let Some(parent) = dst.parent() {
57 let _ = std::fs::create_dir_all(parent);
58 }
59 let _ = std::fs::write(&dst, bytes);
60 }
61 let _ = std::env::set_current_dir(&base);
62}
63
64pub fn run_file(source: &str, source_dir: Option<std::path::PathBuf>) -> Result<(), String> {
66 run_named(source, source_dir, None)
67}
68
69pub fn run_named(
73 source: &str,
74 source_dir: Option<std::path::PathBuf>,
75 file: Option<&str>,
76) -> Result<(), String> {
77 let lang = diag::OutputLang::from_env();
78 let program = parser::parse(source)
79 .map_err(|e| diag::render_parse(&e, source, file, lang))?;
80 let mut interp = runtime::Interpreter::new();
81 interp.source_dir = source_dir;
82 match interp.run_program(&program) {
83 Ok(()) => Ok(()),
84 Err(msg) => {
85 let trace = interp.take_error_trace();
86 Err(diag::render_runtime(&msg, source, file, &trace, lang))
87 }
88 }
89}
90
91pub fn detect_language(source: &str) -> &'static str {
93 let languages: &[(&[&str], &str)] = &[
94 (&["令", "灵符", "执", "函", "核", "若", "否则", "历", "于", "配", "归", "印", "格式"], "Chinese (中文)"),
95 (&["束縛", "実行", "もし", "一方", "ために", "試す", "待つ", "帰る"], "Japanese (日本語)"),
96 (&["바인드", "만약", "동안", "출력", "시작"], "Korean (한국어)"),
97 (&["связать", "сделать", "если", "иначе", "пока", "для", "вернуть", "вывести"], "Russian (русский)"),
98 (&["ผูก", "ทำ", "ถ้า", "มิฉะนั้น", "สำหรับ", "คืน", "พิมพ์", "รูปแบบ", "เริ่ม"], "Thai (ภาษาไทย)"),
99 (&["बाँधो", "करो", "अगर", "जबकि", "वापस", "सत्य"], "Hindi (हिन्दी)"),
100 (&["ربط", "افعل", "إذا", "وإلا", "بينما", "أعد"], "Arabic (العربية)"),
101 (&["enlazar", "hacer", "mientras", "retornar", "verdadero"], "Spanish (Español)"),
102 (&["lier", "faire", "sinon", "tantque", "retourner", "vrai"], "French (Français)"),
103 (&["binden", "machen", "wenn", "solange", "zurück", "wahr"], "German (Deutsch)"),
104 (&["ligar", "fazer", "enquanto", "retornar", "verdadeiro"], "Portuguese (Português)"),
105 ];
106
107 let best = languages.iter()
108 .map(|(keywords, lang)| {
109 let count = keywords.iter().filter(|&&k| source.contains(k)).count();
110 (count, *lang)
111 })
112 .max_by_key(|&(count, _)| count);
113
114 match best {
115 Some((count, lang)) if count > 0 => lang,
116 _ => "English",
117 }
118}