mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
Merge branch 'main' into int_overflow
This commit is contained in:
commit
a81d07f19c
32 changed files with 118 additions and 147 deletions
|
@ -1,4 +1,4 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.17.0/lZFLstMUCUvd5bjnnpYromZJXkQUrdhbva4xdBInicE.tar.br" }
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
app [main] {
|
app [main] {
|
||||||
cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br",
|
cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.17.0/lZFLstMUCUvd5bjnnpYromZJXkQUrdhbva4xdBInicE.tar.br",
|
||||||
}
|
}
|
||||||
|
|
||||||
import cli.Stdout
|
import cli.Stdout
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
app [main] {
|
app [main] {
|
||||||
cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br",
|
cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.17.0/lZFLstMUCUvd5bjnnpYromZJXkQUrdhbva4xdBInicE.tar.br",
|
||||||
}
|
}
|
||||||
|
|
||||||
import Alias { passed: Task.ok {} }
|
import Alias { passed: Task.ok {} }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.17.0/lZFLstMUCUvd5bjnnpYromZJXkQUrdhbva4xdBInicE.tar.br" }
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
import Menu { echo: \str -> Stdout.line str }
|
import Menu { echo: \str -> Stdout.line str }
|
||||||
|
|
|
@ -1453,11 +1453,6 @@ fn expr_spec<'a>(
|
||||||
|
|
||||||
erasure_load(builder, block, value, *field, loaded_type)
|
erasure_load(builder, block, value, *field, loaded_type)
|
||||||
}
|
}
|
||||||
RuntimeErrorFunction(_) => {
|
|
||||||
let type_id = layout_spec(env, builder, interner, interner.get_repr(layout))?;
|
|
||||||
|
|
||||||
builder.add_terminate(block, type_id)
|
|
||||||
}
|
|
||||||
GetTagId { .. } => {
|
GetTagId { .. } => {
|
||||||
// TODO touch heap cell in recursive cases
|
// TODO touch heap cell in recursive cases
|
||||||
|
|
||||||
|
|
|
@ -113,8 +113,6 @@ pub struct SpecializationId(NonZeroU32);
|
||||||
|
|
||||||
static_assertions::assert_eq_size!(SpecializationId, Option<SpecializationId>);
|
static_assertions::assert_eq_size!(SpecializationId, Option<SpecializationId>);
|
||||||
|
|
||||||
pub enum SpecializationLambdaSetError {}
|
|
||||||
|
|
||||||
/// A key into a particular implementation of an ability member for an opaque type.
|
/// A key into a particular implementation of an ability member for an opaque type.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
pub struct ImplKey {
|
pub struct ImplKey {
|
||||||
|
|
|
@ -718,8 +718,6 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
|
||||||
symbol: *symbol,
|
symbol: *symbol,
|
||||||
},
|
},
|
||||||
|
|
||||||
TypedHole(v) => TypedHole(sub!(*v)),
|
|
||||||
|
|
||||||
RuntimeError(err) => RuntimeError(err.clone()),
|
RuntimeError(err) => RuntimeError(err.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -453,7 +453,6 @@ fn expr<'a>(c: &Ctx, p: EPrec, f: &'a Arena<'a>, e: &'a Expr) -> DocBuilder<'a,
|
||||||
Dbg { .. } => todo!(),
|
Dbg { .. } => todo!(),
|
||||||
Expect { .. } => todo!(),
|
Expect { .. } => todo!(),
|
||||||
Return { .. } => todo!(),
|
Return { .. } => todo!(),
|
||||||
TypedHole(_) => todo!(),
|
|
||||||
RuntimeError(_) => todo!(),
|
RuntimeError(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -333,9 +333,6 @@ pub enum Expr {
|
||||||
return_var: Variable,
|
return_var: Variable,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Rendered as empty box in editor
|
|
||||||
TypedHole(Variable),
|
|
||||||
|
|
||||||
/// Compiles, but will crash if reached
|
/// Compiles, but will crash if reached
|
||||||
RuntimeError(RuntimeError),
|
RuntimeError(RuntimeError),
|
||||||
}
|
}
|
||||||
|
@ -411,7 +408,7 @@ impl Expr {
|
||||||
Self::Dbg { .. } => Category::Expect,
|
Self::Dbg { .. } => Category::Expect,
|
||||||
|
|
||||||
// these nodes place no constraints on the expression's type
|
// these nodes place no constraints on the expression's type
|
||||||
Self::TypedHole(_) | Self::RuntimeError(..) => Category::Unknown,
|
Self::RuntimeError(..) => Category::Unknown,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2095,7 +2092,6 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
|
||||||
| other @ ParamsVar { .. }
|
| other @ ParamsVar { .. }
|
||||||
| other @ AbilityMember(..)
|
| other @ AbilityMember(..)
|
||||||
| other @ RunLowLevel { .. }
|
| other @ RunLowLevel { .. }
|
||||||
| other @ TypedHole { .. }
|
|
||||||
| other @ ForeignCall { .. }
|
| other @ ForeignCall { .. }
|
||||||
| other @ OpaqueWrapFunction(_)
|
| other @ OpaqueWrapFunction(_)
|
||||||
| other @ Crash { .. }
|
| other @ Crash { .. }
|
||||||
|
@ -3460,7 +3456,6 @@ pub(crate) fn get_lookup_symbols(expr: &Expr) -> Vec<ExpectLookup> {
|
||||||
| Expr::RecordAccessor(_)
|
| Expr::RecordAccessor(_)
|
||||||
| Expr::SingleQuote(..)
|
| Expr::SingleQuote(..)
|
||||||
| Expr::EmptyRecord
|
| Expr::EmptyRecord
|
||||||
| Expr::TypedHole(_)
|
|
||||||
| Expr::RuntimeError(_)
|
| Expr::RuntimeError(_)
|
||||||
| Expr::ImportParams(_, _, None)
|
| Expr::ImportParams(_, _, None)
|
||||||
| Expr::OpaqueWrapFunction(_) => {}
|
| Expr::OpaqueWrapFunction(_) => {}
|
||||||
|
|
|
@ -1055,7 +1055,6 @@ fn fix_values_captured_in_closure_expr(
|
||||||
| ParamsVar { .. }
|
| ParamsVar { .. }
|
||||||
| AbilityMember(..)
|
| AbilityMember(..)
|
||||||
| EmptyRecord
|
| EmptyRecord
|
||||||
| TypedHole { .. }
|
|
||||||
| RuntimeError(_)
|
| RuntimeError(_)
|
||||||
| ZeroArgumentTag { .. }
|
| ZeroArgumentTag { .. }
|
||||||
| RecordAccessor { .. } => {}
|
| RecordAccessor { .. } => {}
|
||||||
|
|
|
@ -406,7 +406,6 @@ pub fn walk_expr<V: Visitor>(visitor: &mut V, expr: &Expr, var: Variable) {
|
||||||
} => {
|
} => {
|
||||||
visitor.visit_expr(&return_value.value, return_value.region, *return_var);
|
visitor.visit_expr(&return_value.value, return_value.region, *return_var);
|
||||||
}
|
}
|
||||||
Expr::TypedHole(_) => { /* terminal */ }
|
|
||||||
Expr::RuntimeError(..) => { /* terminal */ }
|
Expr::RuntimeError(..) => { /* terminal */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1815,15 +1815,6 @@ pub fn constrain_expr(
|
||||||
arg_cons.push(eq);
|
arg_cons.push(eq);
|
||||||
constraints.exists_many(vars, arg_cons)
|
constraints.exists_many(vars, arg_cons)
|
||||||
}
|
}
|
||||||
TypedHole(var) => {
|
|
||||||
// store the expected type for this position
|
|
||||||
constraints.equal_types_var(
|
|
||||||
*var,
|
|
||||||
expected,
|
|
||||||
Category::Storage(std::file!(), std::line!()),
|
|
||||||
region,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
RuntimeError(_) => {
|
RuntimeError(_) => {
|
||||||
// Runtime Errors are always going to crash, so they don't introduce any new
|
// Runtime Errors are always going to crash, so they don't introduce any new
|
||||||
// constraints.
|
// constraints.
|
||||||
|
@ -4403,7 +4394,6 @@ fn is_generalizable_expr(mut expr: &Expr) -> bool {
|
||||||
| Expect { .. }
|
| Expect { .. }
|
||||||
| Dbg { .. }
|
| Dbg { .. }
|
||||||
| Return { .. }
|
| Return { .. }
|
||||||
| TypedHole(_)
|
|
||||||
| RuntimeError(..)
|
| RuntimeError(..)
|
||||||
| ZeroArgumentTag { .. }
|
| ZeroArgumentTag { .. }
|
||||||
| Tag { .. }
|
| Tag { .. }
|
||||||
|
|
|
@ -209,7 +209,6 @@ impl<'a> LastSeenMap<'a> {
|
||||||
self.set_last_seen(*initializer, stmt);
|
self.set_last_seen(*initializer, stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::RuntimeErrorFunction(_) => {}
|
|
||||||
Expr::FunctionPointer { .. } => todo_lambda_erasure!(),
|
Expr::FunctionPointer { .. } => todo_lambda_erasure!(),
|
||||||
Expr::EmptyArray => {}
|
Expr::EmptyArray => {}
|
||||||
}
|
}
|
||||||
|
@ -1003,7 +1002,6 @@ trait Backend<'a> {
|
||||||
} => {
|
} => {
|
||||||
self.build_alloca(*sym, *initializer, *element_layout);
|
self.build_alloca(*sym, *initializer, *element_layout);
|
||||||
}
|
}
|
||||||
Expr::RuntimeErrorFunction(_) => todo!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1908,7 +1908,6 @@ pub(crate) fn build_exp_expr<'a, 'ctx>(
|
||||||
Array { elem_layout, elems } => {
|
Array { elem_layout, elems } => {
|
||||||
list_literal(env, layout_interner, scope, *elem_layout, elems)
|
list_literal(env, layout_interner, scope, *elem_layout, elems)
|
||||||
}
|
}
|
||||||
RuntimeErrorFunction(_) => todo!(),
|
|
||||||
|
|
||||||
UnionAtIndex {
|
UnionAtIndex {
|
||||||
tag_id,
|
tag_id,
|
||||||
|
|
|
@ -1009,10 +1009,6 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
||||||
initializer,
|
initializer,
|
||||||
element_layout,
|
element_layout,
|
||||||
} => self.expr_alloca(*initializer, *element_layout, storage),
|
} => self.expr_alloca(*initializer, *element_layout, storage),
|
||||||
|
|
||||||
Expr::RuntimeErrorFunction(_) => {
|
|
||||||
todo!("Expression `{}`", expr.to_pretty(100, false))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -389,7 +389,6 @@ impl<'a> LowerParams<'a> {
|
||||||
}
|
}
|
||||||
| OpaqueWrapFunction(_)
|
| OpaqueWrapFunction(_)
|
||||||
| EmptyRecord
|
| EmptyRecord
|
||||||
| TypedHole(_)
|
|
||||||
| RuntimeError(_)
|
| RuntimeError(_)
|
||||||
| Num(_, _, _, _)
|
| Num(_, _, _, _)
|
||||||
| Int(_, _, _, _, _)
|
| Int(_, _, _, _, _)
|
||||||
|
|
|
@ -537,7 +537,6 @@ impl<'a, 'r> Ctx<'a, 'r> {
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Expr::RuntimeErrorFunction(_) => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -244,8 +244,7 @@ fn specialize_drops_stmt<'a, 'i>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reset { .. } | Expr::ResetRef { .. } => { /* do nothing */ }
|
Reset { .. } | Expr::ResetRef { .. } => { /* do nothing */ }
|
||||||
RuntimeErrorFunction(_)
|
FunctionPointer { .. }
|
||||||
| FunctionPointer { .. }
|
|
||||||
| GetTagId { .. }
|
| GetTagId { .. }
|
||||||
| Alloca { .. }
|
| Alloca { .. }
|
||||||
| EmptyArray
|
| EmptyArray
|
||||||
|
|
|
@ -881,12 +881,8 @@ fn insert_refcount_operations_binding<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Literal(_)
|
Expr::Literal(_) | Expr::NullPointer | Expr::FunctionPointer { .. } | Expr::EmptyArray => {
|
||||||
| Expr::NullPointer
|
// Literals and empty arrays are not (and have nothing) reference counted.
|
||||||
| Expr::FunctionPointer { .. }
|
|
||||||
| Expr::EmptyArray
|
|
||||||
| Expr::RuntimeErrorFunction(_) => {
|
|
||||||
// Literals, empty arrays, and runtime errors are not (and have nothing) reference counted.
|
|
||||||
new_let!(stmt)
|
new_let!(stmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1947,8 +1947,6 @@ pub enum Expr<'a> {
|
||||||
symbol: Symbol,
|
symbol: Symbol,
|
||||||
update_mode: UpdateModeId,
|
update_mode: UpdateModeId,
|
||||||
},
|
},
|
||||||
|
|
||||||
RuntimeErrorFunction(&'a str),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Literal<'a> {
|
impl<'a> Literal<'a> {
|
||||||
|
@ -2111,8 +2109,6 @@ impl<'a> Expr<'a> {
|
||||||
} => text!(alloc, "StructAtIndex {} ", index)
|
} => text!(alloc, "StructAtIndex {} ", index)
|
||||||
.append(symbol_to_doc(alloc, *structure, pretty)),
|
.append(symbol_to_doc(alloc, *structure, pretty)),
|
||||||
|
|
||||||
RuntimeErrorFunction(s) => text!(alloc, "ErrorFunction {}", s),
|
|
||||||
|
|
||||||
GetTagId { structure, .. } => alloc
|
GetTagId { structure, .. } => alloc
|
||||||
.text("GetTagId ")
|
.text("GetTagId ")
|
||||||
.append(symbol_to_doc(alloc, *structure, pretty)),
|
.append(symbol_to_doc(alloc, *structure, pretty)),
|
||||||
|
@ -5897,7 +5893,6 @@ pub fn with_hole<'a>(
|
||||||
Stmt::Ret(return_symbol),
|
Stmt::Ret(return_symbol),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
TypedHole(_) => runtime_error(env, "Hit a blank"),
|
|
||||||
RuntimeError(e) => runtime_error(env, env.arena.alloc(e.runtime_message())),
|
RuntimeError(e) => runtime_error(env, env.arena.alloc(e.runtime_message())),
|
||||||
Crash { msg, ret_var: _ } => {
|
Crash { msg, ret_var: _ } => {
|
||||||
let msg_sym = possible_reuse_symbol_or_specialize(
|
let msg_sym = possible_reuse_symbol_or_specialize(
|
||||||
|
@ -7729,7 +7724,7 @@ fn substitute_in_expr<'a>(
|
||||||
use Expr::*;
|
use Expr::*;
|
||||||
|
|
||||||
match expr {
|
match expr {
|
||||||
Literal(_) | EmptyArray | RuntimeErrorFunction(_) => None,
|
Literal(_) | EmptyArray => None,
|
||||||
|
|
||||||
Call(call) => substitute_in_call(arena, call, subs).map(Expr::Call),
|
Call(call) => substitute_in_call(arena, call, subs).map(Expr::Call),
|
||||||
|
|
||||||
|
|
|
@ -1070,7 +1070,6 @@ fn expr_contains_symbol(expr: &Expr, needle: Symbol) -> bool {
|
||||||
}),
|
}),
|
||||||
Expr::EmptyArray => false,
|
Expr::EmptyArray => false,
|
||||||
Expr::Reset { symbol, .. } | Expr::ResetRef { symbol, .. } => needle == *symbol,
|
Expr::Reset { symbol, .. } | Expr::ResetRef { symbol, .. } => needle == *symbol,
|
||||||
Expr::RuntimeErrorFunction(_) => false,
|
|
||||||
Expr::ErasedMake { value, callee } => {
|
Expr::ErasedMake { value, callee } => {
|
||||||
value.map(|v| v == needle).unwrap_or(false) || needle == *callee
|
value.map(|v| v == needle).unwrap_or(false) || needle == *callee
|
||||||
}
|
}
|
||||||
|
|
|
@ -3416,9 +3416,6 @@ pub enum RecordField<'a> {
|
||||||
SpaceAfter(&'a RecordField<'a>, &'a [CommentOrNewline<'a>]),
|
SpaceAfter(&'a RecordField<'a>, &'a [CommentOrNewline<'a>]),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct FoundApplyValue;
|
|
||||||
|
|
||||||
impl<'a> RecordField<'a> {
|
impl<'a> RecordField<'a> {
|
||||||
fn is_ignored_value(&self) -> bool {
|
fn is_ignored_value(&self) -> bool {
|
||||||
let mut current = self;
|
let mut current = self;
|
||||||
|
|
|
@ -289,7 +289,6 @@ fn monomorphize_expr(expr: Expr, subs: &mut Subs) -> Expr {
|
||||||
variable: monomorphize_var(variable, subs),
|
variable: monomorphize_var(variable, subs),
|
||||||
symbol,
|
symbol,
|
||||||
},
|
},
|
||||||
Expr::TypedHole(var) => Expr::TypedHole(monomorphize_var(var, subs)),
|
|
||||||
Expr::RuntimeError(error) => Expr::RuntimeError(error),
|
Expr::RuntimeError(error) => Expr::RuntimeError(error),
|
||||||
Expr::RunLowLevel { op, args, ret_var } => Expr::RunLowLevel {
|
Expr::RunLowLevel { op, args, ret_var } => Expr::RunLowLevel {
|
||||||
op,
|
op,
|
||||||
|
|
|
@ -386,7 +386,6 @@ impl<'a, 'c, 'd, 'i, 's, 't, P: Push<Problem>> Env<'a, 'c, 'd, 'i, 's, 't, P> {
|
||||||
// variable,
|
// variable,
|
||||||
// symbol,
|
// symbol,
|
||||||
// } => todo!(),
|
// } => todo!(),
|
||||||
// Expr::TypedHole(variable) => todo!(),
|
|
||||||
// Expr::RuntimeError(_runtime_error) => {
|
// Expr::RuntimeError(_runtime_error) => {
|
||||||
// todo!("generate a MonoExpr::Crash based on the runtime error");
|
// todo!("generate a MonoExpr::Crash based on the runtime error");
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -234,11 +234,11 @@ fn render_package_index(docs_by_module: &[(ModuleId, ModuleDocumentation)]) -> S
|
||||||
push_html(
|
push_html(
|
||||||
&mut link_buf,
|
&mut link_buf,
|
||||||
"a",
|
"a",
|
||||||
vec![("href", module.name.as_str())],
|
[("href", module.name.as_str())],
|
||||||
module.name.as_str(),
|
module.name.as_str(),
|
||||||
);
|
);
|
||||||
|
|
||||||
push_html(&mut module_list_buf, "li", vec![], link_buf.as_str());
|
push_html(&mut module_list_buf, "li", [], link_buf.as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// The HTML for the index page
|
// The HTML for the index page
|
||||||
|
@ -247,13 +247,13 @@ fn render_package_index(docs_by_module: &[(ModuleId, ModuleDocumentation)]) -> S
|
||||||
push_html(
|
push_html(
|
||||||
&mut index_buf,
|
&mut index_buf,
|
||||||
"h2",
|
"h2",
|
||||||
vec![("class", "module-name")],
|
[("class", "module-name")],
|
||||||
"Exposed Modules",
|
"Exposed Modules",
|
||||||
);
|
);
|
||||||
push_html(
|
push_html(
|
||||||
&mut index_buf,
|
&mut index_buf,
|
||||||
"ul",
|
"ul",
|
||||||
vec![("class", "index-module-links")],
|
[("class", "index-module-links")],
|
||||||
module_list_buf.as_str(),
|
module_list_buf.as_str(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -269,10 +269,10 @@ fn render_module_documentation(
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
let module_name = module.name.as_str();
|
let module_name = module.name.as_str();
|
||||||
|
|
||||||
push_html(&mut buf, "h2", vec![("class", "module-name")], {
|
push_html(&mut buf, "h2", [("class", "module-name")], {
|
||||||
let mut link_buf = String::new();
|
let mut link_buf = String::new();
|
||||||
|
|
||||||
push_html(&mut link_buf, "a", vec![("href", "/")], module_name);
|
push_html(&mut link_buf, "a", [("href", "/")], module_name);
|
||||||
|
|
||||||
link_buf
|
link_buf
|
||||||
});
|
});
|
||||||
|
@ -288,8 +288,8 @@ fn render_module_documentation(
|
||||||
let href = format!("{module_name}#{def_name}");
|
let href = format!("{module_name}#{def_name}");
|
||||||
let mut content = String::new();
|
let mut content = String::new();
|
||||||
|
|
||||||
push_html(&mut content, "a", vec![("href", href.as_str())], LINK_SVG);
|
push_html(&mut content, "a", [("href", href.as_str())], LINK_SVG);
|
||||||
push_html(&mut content, "strong", vec![], def_name);
|
push_html(&mut content, "strong", [], def_name);
|
||||||
|
|
||||||
for type_var in &doc_def.type_vars {
|
for type_var in &doc_def.type_vars {
|
||||||
content.push(' ');
|
content.push(' ');
|
||||||
|
@ -312,7 +312,7 @@ fn render_module_documentation(
|
||||||
push_html(
|
push_html(
|
||||||
&mut buf,
|
&mut buf,
|
||||||
"h3",
|
"h3",
|
||||||
vec![("id", def_name), ("class", "entry-name")],
|
[("id", def_name), ("class", "entry-name")],
|
||||||
content.as_str(),
|
content.as_str(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -356,19 +356,19 @@ fn render_module_documentation(
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_html(buf: &mut String, tag_name: &str, attrs: Vec<(&str, &str)>, content: impl AsRef<str>) {
|
fn push_html<'a, 'b, I>(buf: &mut String, tag_name: &str, attrs: I, content: impl AsRef<str>)
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = (&'a str, &'b str)>,
|
||||||
|
{
|
||||||
buf.push('<');
|
buf.push('<');
|
||||||
buf.push_str(tag_name);
|
buf.push_str(tag_name);
|
||||||
|
buf.push(' ');
|
||||||
|
|
||||||
for (key, value) in &attrs {
|
for (key, value) in attrs.into_iter() {
|
||||||
buf.push(' ');
|
|
||||||
buf.push_str(key);
|
buf.push_str(key);
|
||||||
buf.push_str("=\"");
|
buf.push_str("=\"");
|
||||||
buf.push_str(value);
|
buf.push_str(value);
|
||||||
buf.push('"');
|
buf.push('"');
|
||||||
}
|
|
||||||
|
|
||||||
if !&attrs.is_empty() {
|
|
||||||
buf.push(' ');
|
buf.push(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,16 +415,11 @@ fn base_url() -> String {
|
||||||
fn render_name_link(name: &str) -> String {
|
fn render_name_link(name: &str) -> String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
|
|
||||||
push_html(&mut buf, "h1", vec![("class", "pkg-full-name")], {
|
push_html(&mut buf, "h1", [("class", "pkg-full-name")], {
|
||||||
let mut link_buf = String::new();
|
let mut link_buf = String::new();
|
||||||
|
|
||||||
// link to root (= docs overview page)
|
// link to root (= docs overview page)
|
||||||
push_html(
|
push_html(&mut link_buf, "a", [("href", base_url().as_str())], name);
|
||||||
&mut link_buf,
|
|
||||||
"a",
|
|
||||||
vec![("href", base_url().as_str())],
|
|
||||||
name,
|
|
||||||
);
|
|
||||||
|
|
||||||
link_buf
|
link_buf
|
||||||
});
|
});
|
||||||
|
@ -442,7 +437,7 @@ fn render_sidebar<'a, I: Iterator<Item = &'a ModuleDocumentation>>(modules: I) -
|
||||||
push_html(
|
push_html(
|
||||||
&mut sidebar_entry_content,
|
&mut sidebar_entry_content,
|
||||||
"a",
|
"a",
|
||||||
vec![("class", "sidebar-module-link"), ("href", href)],
|
[("class", "sidebar-module-link"), ("href", href)],
|
||||||
module.name.as_str(),
|
module.name.as_str(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -461,7 +456,7 @@ fn render_sidebar<'a, I: Iterator<Item = &'a ModuleDocumentation>>(modules: I) -
|
||||||
push_html(
|
push_html(
|
||||||
&mut entries_buf,
|
&mut entries_buf,
|
||||||
"a",
|
"a",
|
||||||
vec![("href", entry_href.as_str())],
|
[("href", entry_href.as_str())],
|
||||||
doc_def.name.as_str(),
|
doc_def.name.as_str(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -474,14 +469,14 @@ fn render_sidebar<'a, I: Iterator<Item = &'a ModuleDocumentation>>(modules: I) -
|
||||||
push_html(
|
push_html(
|
||||||
&mut sidebar_entry_content,
|
&mut sidebar_entry_content,
|
||||||
"div",
|
"div",
|
||||||
vec![("class", "sidebar-sub-entries")],
|
[("class", "sidebar-sub-entries")],
|
||||||
entries.as_str(),
|
entries.as_str(),
|
||||||
);
|
);
|
||||||
|
|
||||||
push_html(
|
push_html(
|
||||||
&mut buf,
|
&mut buf,
|
||||||
"div",
|
"div",
|
||||||
vec![("class", "sidebar-entry")],
|
[("class", "sidebar-entry")],
|
||||||
sidebar_entry_content.as_str(),
|
sidebar_entry_content.as_str(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -497,56 +492,56 @@ fn render_search_type_ahead<'a, I: Iterator<Item = &'a ModuleDocumentation>>(mod
|
||||||
if let DocEntry::DocDef(doc_def) = entry {
|
if let DocEntry::DocDef(doc_def) = entry {
|
||||||
if module.exposed_symbols.contains(&doc_def.symbol) {
|
if module.exposed_symbols.contains(&doc_def.symbol) {
|
||||||
let mut entry_contents_buf = String::new();
|
let mut entry_contents_buf = String::new();
|
||||||
|
|
||||||
push_html(
|
push_html(
|
||||||
&mut entry_contents_buf,
|
&mut entry_contents_buf,
|
||||||
"p",
|
"span",
|
||||||
vec![("class", "type-ahead-def-name")],
|
[("class", "type-ahead-module-name")],
|
||||||
doc_def.name.as_str(),
|
module_name,
|
||||||
);
|
|
||||||
|
|
||||||
let mut entry_signature_buf = String::new();
|
|
||||||
type_annotation_to_html(
|
|
||||||
0,
|
|
||||||
&mut entry_signature_buf,
|
|
||||||
&doc_def.type_annotation,
|
|
||||||
false,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
push_html(
|
push_html(
|
||||||
&mut entry_contents_buf,
|
&mut entry_contents_buf,
|
||||||
"p",
|
"span",
|
||||||
vec![("class", "type-ahead-signature")],
|
[("class", "type-ahead-module-dot")],
|
||||||
entry_signature_buf.as_str(),
|
".",
|
||||||
);
|
);
|
||||||
|
|
||||||
push_html(
|
push_html(
|
||||||
&mut entry_contents_buf,
|
&mut entry_contents_buf,
|
||||||
"p",
|
"span",
|
||||||
vec![("class", "type-ahead-doc-path")],
|
[("class", "type-ahead-def-name")],
|
||||||
format!("{} > {}", module_name, doc_def.name),
|
&doc_def.name,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut type_ann_buf = String::new();
|
||||||
|
type_annotation_to_html(0, &mut type_ann_buf, &doc_def.type_annotation, false);
|
||||||
|
|
||||||
|
if !type_ann_buf.is_empty() {
|
||||||
|
push_html(
|
||||||
|
&mut entry_contents_buf,
|
||||||
|
"span",
|
||||||
|
[("class", "type-ahead-signature")],
|
||||||
|
format!(" : {type_ann_buf}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let mut entry_href = String::new();
|
let mut entry_href = String::new();
|
||||||
|
|
||||||
entry_href.push_str(module_name);
|
entry_href.push_str(module_name);
|
||||||
entry_href.push('#');
|
entry_href.push('#');
|
||||||
entry_href.push_str(doc_def.name.as_str());
|
entry_href.push_str(&doc_def.name);
|
||||||
|
|
||||||
let mut anchor_buf = String::new();
|
let mut anchor_buf = String::new();
|
||||||
|
|
||||||
push_html(
|
push_html(
|
||||||
&mut anchor_buf,
|
&mut anchor_buf,
|
||||||
"a",
|
"a",
|
||||||
vec![("href", entry_href.as_str()), ("class", "type-ahead-link")],
|
[("href", entry_href.as_str()), ("class", "type-ahead-link")],
|
||||||
entry_contents_buf.as_str(),
|
&entry_contents_buf,
|
||||||
);
|
);
|
||||||
|
|
||||||
push_html(
|
push_html(&mut buf, "li", [("role", "option")], &anchor_buf);
|
||||||
&mut buf,
|
|
||||||
"li",
|
|
||||||
vec![("role", "option")],
|
|
||||||
anchor_buf.as_str(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1281,7 +1276,7 @@ fn markdown_to_html(
|
||||||
let mut in_code_block: Option<CowStr> = None;
|
let mut in_code_block: Option<CowStr> = None;
|
||||||
let mut to_highlight = String::new();
|
let mut to_highlight = String::new();
|
||||||
|
|
||||||
let mut docs_parser = vec![];
|
let mut docs_parser = Vec::new();
|
||||||
let parser = pulldown_cmark::Parser::new_with_broken_link_callback(
|
let parser = pulldown_cmark::Parser::new_with_broken_link_callback(
|
||||||
markdown,
|
markdown,
|
||||||
markdown_options,
|
markdown_options,
|
||||||
|
|
|
@ -1,24 +1,26 @@
|
||||||
(() => {
|
(() => {
|
||||||
|
|
||||||
let sidebar = document.getElementById("sidebar-nav");
|
let sidebar = document.getElementById("sidebar-nav");
|
||||||
// Un-hide everything
|
|
||||||
sidebar
|
if (sidebar != null) {
|
||||||
|
// Un-hide everything
|
||||||
|
sidebar
|
||||||
.querySelectorAll(".sidebar-entry a")
|
.querySelectorAll(".sidebar-entry a")
|
||||||
.forEach((entry) => entry.classList.remove("hidden"));
|
.forEach((entry) => entry.classList.remove("hidden"));
|
||||||
|
|
||||||
// Re-hide all the sub-entries except for those of the current module
|
// Re-hide all the sub-entries except for those of the current module
|
||||||
let currentModuleName = document.querySelector(".module-name").textContent;
|
let currentModuleName = document.querySelector(".module-name").textContent;
|
||||||
|
|
||||||
sidebar.querySelectorAll(".sidebar-entry").forEach((entry) => {
|
sidebar.querySelectorAll(".sidebar-entry").forEach((entry) => {
|
||||||
let entryName = entry.querySelector(".sidebar-module-link").textContent;
|
let entryName = entry.querySelector(".sidebar-module-link").textContent;
|
||||||
if (currentModuleName === entryName) {
|
if (currentModuleName === entryName) {
|
||||||
entry.firstChild.classList.add("active");
|
entry.firstChild.classList.add("active");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
entry
|
entry
|
||||||
.querySelectorAll(".sidebar-sub-entries a")
|
.querySelectorAll(".sidebar-sub-entries a")
|
||||||
.forEach((subEntry) => subEntry.classList.add("hidden"));
|
.forEach((subEntry) => subEntry.classList.add("hidden"));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let searchTypeAhead = document.getElementById("search-type-ahead");
|
let searchTypeAhead = document.getElementById("search-type-ahead");
|
||||||
let searchBox = document.getElementById("module-search");
|
let searchBox = document.getElementById("module-search");
|
||||||
|
@ -41,13 +43,13 @@
|
||||||
.textContent.toLowerCase();
|
.textContent.toLowerCase();
|
||||||
const entrySignature = entry
|
const entrySignature = entry
|
||||||
.querySelector(".type-ahead-signature")
|
.querySelector(".type-ahead-signature")
|
||||||
.textContent.toLowerCase()
|
?.textContent?.toLowerCase()
|
||||||
.replace(/\s+/g, "");
|
?.replace(/\s+/g, "");
|
||||||
|
|
||||||
if (
|
if (
|
||||||
totalResults < 5 &&
|
totalResults < 5 &&
|
||||||
(entryName.includes(text) ||
|
(entryName.includes(text) ||
|
||||||
entrySignature.includes(text.replace(/\s+/g, "")))
|
entrySignature?.includes(text.replace(/\s+/g, "")))
|
||||||
) {
|
) {
|
||||||
totalResults++;
|
totalResults++;
|
||||||
entry.classList.remove("hidden");
|
entry.classList.remove("hidden");
|
||||||
|
|
|
@ -482,8 +482,9 @@ pre>samp {
|
||||||
}
|
}
|
||||||
|
|
||||||
#search-type-ahead {
|
#search-type-ahead {
|
||||||
|
font-family: var(--font-mono);
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 20px;
|
gap: 0px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: calc(var(--module-search-padding-height) + var(--module-search-height));
|
top: calc(var(--module-search-padding-height) + var(--module-search-height));
|
||||||
|
@ -501,20 +502,23 @@ pre>samp {
|
||||||
}
|
}
|
||||||
|
|
||||||
#search-type-ahead .type-ahead-link {
|
#search-type-ahead .type-ahead-link {
|
||||||
font-size: 0.875rem;
|
font-size: 1rem;
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
p {
|
line-height: 2em;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
/* if it wraps, indent after the first line */
|
||||||
|
padding-left: 2em;
|
||||||
|
text-indent: -2em;
|
||||||
|
|
||||||
|
span {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.type-ahead-def-name {
|
.type-ahead-module-name, .type-ahead-def-name {
|
||||||
color: var(--violet);
|
color: var(--violet);
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
p.type-ahead-doc-path {
|
|
||||||
font-size: 0.75rem;
|
|
||||||
color: var(--faded-color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#search-type-ahead li {
|
#search-type-ahead li {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
@ -545,7 +549,7 @@ pre>samp {
|
||||||
}
|
}
|
||||||
|
|
||||||
#search-shortcut-key {
|
#search-shortcut-key {
|
||||||
font-family: monospace;
|
font-family: var(--font-mono);
|
||||||
border: 1px solid #666;
|
border: 1px solid #666;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 1px 3px 3px;
|
padding: 1px 3px 3px;
|
||||||
|
|
|
@ -84,7 +84,14 @@ else
|
||||||
echo 'Fetching latest roc nightly...'
|
echo 'Fetching latest roc nightly...'
|
||||||
|
|
||||||
# get roc release archive
|
# get roc release archive
|
||||||
curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-linux_x86_64-latest.tar.gz
|
# check if testing archive is available
|
||||||
|
TESTING_URL="https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-linux_x86_64-TESTING.tar.gz"
|
||||||
|
LATEST_URL="https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-linux_x86_64-latest.tar.gz"
|
||||||
|
if curl --output /dev/null --silent --head --fail "$TESTING_URL"; then
|
||||||
|
curl -fOL "$TESTING_URL"
|
||||||
|
else
|
||||||
|
curl -fOL "$LATEST_URL"
|
||||||
|
fi
|
||||||
# extract archive
|
# extract archive
|
||||||
ls | grep "roc_nightly" | xargs tar -xzvf
|
ls | grep "roc_nightly" | xargs tar -xzvf
|
||||||
# delete archive
|
# delete archive
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
- [builtins](/builtins) - docs for modules built into the language—`Str`, `Num`, etc.
|
- [builtins](/builtins) - docs for modules built into the language—`Str`, `Num`, etc.
|
||||||
- [basic-webserver](https://roc-lang.github.io/basic-webserver/) - a platform for making Web servers ([source code](https://github.com/roc-lang/basic-webserver))
|
- [basic-webserver](https://roc-lang.github.io/basic-webserver/) - a platform for making Web servers ([source code](https://github.com/roc-lang/basic-webserver))
|
||||||
- [basic-cli](/packages/basic-cli/0.16.0) - a platform for making command-line interfaces ([source code](https://github.com/roc-lang/basic-cli))
|
- [basic-cli](/packages/basic-cli/0.17.0) - a platform for making command-line interfaces ([source code](https://github.com/roc-lang/basic-cli))
|
||||||
- [plans](/plans) - current plans for future changes to the language
|
- [plans](/plans) - current plans for future changes to the language
|
||||||
|
|
||||||
In the future, a language reference will be on this page too.
|
In the future, a language reference will be on this page too.
|
||||||
|
|
|
@ -27,13 +27,13 @@ Here are some Getting Started guides for different operating systems:
|
||||||
### [Editor Extensions/Plugins](#editor-extensions) {#editor-extensions}
|
### [Editor Extensions/Plugins](#editor-extensions) {#editor-extensions}
|
||||||
|
|
||||||
- [Visual Studio Code](https://visualstudio.microsoft.com/#vscode-section)
|
- [Visual Studio Code](https://visualstudio.microsoft.com/#vscode-section)
|
||||||
- Features: syntax highlighting, completion, type hints, jump to source
|
- Features: syntax highlighting, completion, type hints, jump to source
|
||||||
- syntax highlighting, completion, type hints, jump to source
|
- syntax highlighting, completion, type hints, jump to source
|
||||||
- install the [Roc Plugin](https://marketplace.visualstudio.com/items?itemName=IvanDemchenko.roc-lang-unofficial)
|
- install the [Roc Plugin](https://marketplace.visualstudio.com/items?itemName=IvanDemchenko.roc-lang-unofficial)
|
||||||
- ❗make sure to follow ["Configuring language server"](https://github.com/ivan-demchenko/roc-vscode-unofficial?tab=readme-ov-file#configuring-language-server).
|
- ❗make sure to follow ["Configuring language server"](https://github.com/ivan-demchenko/roc-vscode-unofficial?tab=readme-ov-file#configuring-language-server).
|
||||||
- It would be a fantastic contribution for the language server to be set up automatically. If you'd like to help with this, just make a post in [the "new contributors" topic on Zulip](https://roc.zulipchat.com/#narrow/stream/316715-contributing/topic/new.20contributors) and say hello!
|
- It would be a fantastic contribution for the language server to be set up automatically. If you'd like to help with this, just make a post in [the "new contributors" topic on Zulip](https://roc.zulipchat.com/#narrow/stream/316715-contributing/topic/new.20contributors) and say hello!
|
||||||
- [Zed](https://zed.dev/download), since Version 0.133.5
|
- [Zed](https://zed.dev/download), since Version 0.133.5
|
||||||
- Features: syntax highlighting, completion, type hints, jump to source
|
- Features: syntax highlighting, completion, type hints, jump to source
|
||||||
- search and install roc extension (action `zed: extensions`)
|
- search and install roc extension (action `zed: extensions`)
|
||||||
- in case of errors look into the Zed log (action `zed: open log`)
|
- in case of errors look into the Zed log (action `zed: open log`)
|
||||||
- For other editors like Vim, Helix or Emacs [see](https://github.com/faldor20/tree-sitter-roc)
|
- For other editors like Vim, Helix or Emacs [see](https://github.com/faldor20/tree-sitter-roc)
|
||||||
|
@ -43,3 +43,12 @@ Here are some Getting Started guides for different operating systems:
|
||||||
Once you've installed <code>roc</code>, check out the [tutorial](/tutorial) to learn how to Roc!
|
Once you've installed <code>roc</code>, check out the [tutorial](/tutorial) to learn how to Roc!
|
||||||
|
|
||||||
<a class="btn-small" href="/tutorial">Start Tutorial</a>
|
<a class="btn-small" href="/tutorial">Start Tutorial</a>
|
||||||
|
|
||||||
|
### [Additional Learning Resources] {#additional-learning-resources}
|
||||||
|
|
||||||
|
If you are looking for more resources to learn about Roc, check out the following:
|
||||||
|
|
||||||
|
- [Roc Examples](/examples)
|
||||||
|
- [Roc Guides](/docs#guides)
|
||||||
|
- [Roc Language Reference](/docs#language-reference)
|
||||||
|
- [Roc Exercism Track](https://exercism.org/tracks/roc)
|
||||||
|
|
|
@ -7,7 +7,7 @@ Something that sets Roc apart from other programming languages is its <span clas
|
||||||
Here is a Roc application that prints `"Hello, World!"` to the command line:
|
Here is a Roc application that prints `"Hello, World!"` to the command line:
|
||||||
|
|
||||||
```roc
|
```roc
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.17.0/lZFLstMUCUvd5bjnnpYromZJXkQUrdhbva4xdBInicE.tar.br" }
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ Let's move out of the REPL and create our first Roc application!
|
||||||
Make a file named `main.roc` and put this in it:
|
Make a file named `main.roc` and put this in it:
|
||||||
|
|
||||||
```roc
|
```roc
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.17.0/lZFLstMUCUvd5bjnnpYromZJXkQUrdhbva4xdBInicE.tar.br" }
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
|
|
||||||
|
@ -1511,7 +1511,7 @@ Besides being built into the compiler, the builtin modules are different from ot
|
||||||
Let's take a closer look at the part of `main.roc` above the `main` def:
|
Let's take a closer look at the part of `main.roc` above the `main` def:
|
||||||
|
|
||||||
```roc
|
```roc
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.17.0/lZFLstMUCUvd5bjnnpYromZJXkQUrdhbva4xdBInicE.tar.br" }
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
```
|
```
|
||||||
|
@ -1629,7 +1629,7 @@ We'll use these four operations to learn about tasks.
|
||||||
Let's start with a basic "Hello World" program.
|
Let's start with a basic "Hello World" program.
|
||||||
|
|
||||||
```roc
|
```roc
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.17.0/lZFLstMUCUvd5bjnnpYromZJXkQUrdhbva4xdBInicE.tar.br" }
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
|
|
||||||
|
@ -1664,7 +1664,7 @@ Once this task runs, we'll end up with the [tag union](https://www.roc-lang.org/
|
||||||
Let's change `main` to read a line from `stdin`, and then print what we got:
|
Let's change `main` to read a line from `stdin`, and then print what we got:
|
||||||
|
|
||||||
```roc
|
```roc
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.17.0/lZFLstMUCUvd5bjnnpYromZJXkQUrdhbva4xdBInicE.tar.br" }
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
import pf.Stdin
|
import pf.Stdin
|
||||||
|
@ -2335,3 +2335,9 @@ Here are various Roc expressions involving operators, and what they desugar to.
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
<script type="text/javascript" src="/builtins/search.js" defer></script>
|
<script type="text/javascript" src="/builtins/search.js" defer></script>
|
||||||
|
|
||||||
|
### [Additional Resources]
|
||||||
|
|
||||||
|
You've completed the tutorial, well done!
|
||||||
|
|
||||||
|
If you are looking for more resources to learn Roc, check out [these links](/install#additional-learning-resources).
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue