// Phase 2 of the error system (docs/en/reference/errors.md): the operator ? passes an
// error up to the caller, the context helpers convert typed errors and wrap
// them, and main itself returns a result: on an error the program prints the
// frame "the program ended with an error" in its language and the error's
// description, and exits with status 1.
import std.error.failure;
import std.error.context;
import std.error.from_number;
import std.text.number;
import std.io.println;
import std.text.from_bytes;
def read_port(text: string): result int, Error {
// A number parse error is a typed error; to_error turns it into an
// Error before ? passes it on.
let port: int = to_error(parse_int(&text), error_from_integer_parse_error)?;
if (port < 1 || port > 65535) {
return result.err(error_with_kind("server", "منفذ_خارج_المدى", "يجب أن يكون المنفذ بين 1 و65535"));
};
return result.ok(port);
}
def first_of(values: &vector string): option string {
if ((length(*values) as uint) == 0) { return option.none(); };
return option.some(copy_text(&(*values)[0]));
}
// ? on an option in a function returning an option passes the absence on.
def first_written_port(values: &vector string): option string {
let first: string = first_of(values)?;
return option.some(first);
}
def main(): result int, Error {
let values: mutable vector string = [];
append(values, "8080");
match first_written_port(&values) with
| option.some(text) -> {
let port: int = with_context(read_port(text), "أثناء بدء الخادم")?;
let ignored: result int, int = println(int_to_text(port));
}
| option.none -> { };
return result.ok(0);
}// المرحلة الثانية من نظام الأخطاء (docs/en/reference/errors.md): العامل ؟ يمرر الخطأ إلى
// المستدعي، ومساعدات السياق تحول الأخطاء ذات الأنواع وتغلفها، والرئيسية نفسها
// ترجع نتيجة: عند الخطأ يطبع البرنامج إطار «انتهى البرنامج بخطأ» بلغته ووصف
// الخطأ، ويخرج بالرمز 1.
استورد المكتبة.أخطاء.failure;
استورد المكتبة.أخطاء.context;
استورد المكتبة.أخطاء.from_number;
استورد المكتبة.نصوص.number;
استورد المكتبة.دخ.println;
استورد المكتبة.نصوص.from_bytes;
عرف اقرأ_المنفذ(النص: نص): نتيجة عدد, فشل {
// خطأ تحليل العدد خطأ ذو نوع؛ إلى_فشل يحوله فشلا قبل أن يمرره ؟.
دع المنفذ: عدد = إلى_فشل(حلل_عدد(&النص), فشل_من_خطأ_تحليل_عدد)؟;
إذا (المنفذ < 1 || المنفذ > 65535) {
أرجع نتيجة.خطأ(فشل_بهوية(«server», «منفذ_خارج_المدى», «يجب أن يكون المنفذ بين 1 و65535»));
};
أرجع نتيجة.نجح(المنفذ);
}
عرف اختر_الأول(القيم: &متجه نص): اختياري نص {
إذا ((الطول(*القيم) مثل طبيعي) == 0) { أرجع اختياري.لا_شيء(); };
أرجع اختياري.موجود(انسخ_نص(&(*القيم)[0]));
}
// ؟ على اختيار في دالة ترجع اختيارا يمرر الغياب.
عرف أول_منفذ_مكتوب(القيم: &متجه نص): اختياري نص {
دع الأول: نص = اختر_الأول(القيم)؟;
أرجع اختياري.موجود(الأول);
}
عرف الرئيسية(): نتيجة عدد, فشل {
دع القيم: متغير متجه نص = [];
ألحق(القيم, «8080»);
طابق أول_منفذ_مكتوب(&القيم) مع
| اختياري.موجود(النص) -> {
دع المنفذ: عدد = مع_سياق(اقرأ_المنفذ(النص), «أثناء بدء الخادم»)؟;
دع تجاهل: نتيجة عدد, عدد = اطبع_سطر(عدد_إلى_نص(المنفذ));
}
| اختياري.لا_شيء -> { };
أرجع نتيجة.نجح(0);
}
Run it
With the interpreter, without compiling:
./build/sultanc run examples/en/errors/propagation.snOr compile it to an executable:
./build/sultanc examples/en/errors/propagation.sn -o build/example && ./build/example