mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-11 05:34:11 +03:00
Merge branch 'trunk' into str-refcount
This commit is contained in:
commit
a2069a88db
@ -24,7 +24,9 @@ That will help us improve this document for everyone who reads it in the future!
|
||||
### LLVM installation on Linux
|
||||
|
||||
On some Linux systems we've seen the error "failed to run custom build command for x11".
|
||||
On Ubuntu, running `sudo apt-get install cmake libx11-dev` fixed this.
|
||||
On Ubuntu, running `sudo apt install pkg-config cmake libx11-dev` fixed this.
|
||||
|
||||
If you encounter `cannot find -lz` run `sudo apt install zlib1g-dev`.
|
||||
|
||||
### LLVM installation on macOS
|
||||
|
||||
|
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -579,6 +579,9 @@ dependencies = [
|
||||
"fs_extra",
|
||||
"handlebars",
|
||||
"pulldown-cmark",
|
||||
"roc_builtins",
|
||||
"roc_collections",
|
||||
"roc_load",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
|
@ -1,5 +1,5 @@
|
||||
interface Bool
|
||||
exposes [ not, isEq, isNe ]
|
||||
interface Bool2
|
||||
exposes [ not, and, or, xor, isEq, isNotEq ]
|
||||
imports []
|
||||
|
||||
## Returns #False when given #True, and vice versa.
|
||||
@ -76,7 +76,9 @@ xor : Bool, Bool -> Bool
|
||||
##
|
||||
## Note that `isEq` takes `'val` instead of `val`, which means `isEq` does not
|
||||
## accept arguments whose types contain functions.
|
||||
isEq : 'val, 'val -> Bool
|
||||
# TODO: removed `'` from signature because parser does not support it yet
|
||||
# Original signature: `isEq : 'val, 'val -> Bool`
|
||||
isEq : val, val -> Bool
|
||||
|
||||
## Calls #eq on the given values, then calls #not on the result.
|
||||
##
|
||||
@ -84,4 +86,6 @@ isEq : 'val, 'val -> Bool
|
||||
##
|
||||
## Note that `isNotEq` takes `'val` instead of `val`, which means `isNotEq` does not
|
||||
## accept arguments whose types contain functions.
|
||||
isNotEq : 'val, 'val -> Bool
|
||||
# TODO: removed `'` from signature because parser does not support it yet
|
||||
# Original signature: `isNotEq : 'val, 'val -> Bool`
|
||||
isNotEq : val, val -> Bool
|
||||
|
@ -1,5 +1,5 @@
|
||||
interface List
|
||||
exposes [ List, map, fold ]
|
||||
interface List2
|
||||
exposes [ List, single, empty, repeat, range, reverse, sort, map, mapWithIndex, mapOrCancel, mapOks, update, updater, allOks, append, prepend, concat, join, joinMap, oks, zip, zipMap, keepIf, dropIf, first, last, get, max, min, put, drop, append, prepend, dropLast, dropFirst, takeFirst, takeLast, split, sublist, walk, walkBackwards, walkUntil, walkBackwardsUntil, len, isEmpty, contains, all, any ]
|
||||
imports []
|
||||
|
||||
## Types
|
||||
|
@ -1,16 +1,16 @@
|
||||
interface Map
|
||||
exposes [ Map, isEmpty ]
|
||||
interface Map2
|
||||
exposes [ isEmpty, map ]
|
||||
imports []
|
||||
|
||||
isEmpty : Map * * -> Bool
|
||||
|
||||
## Convert each key and value in the #Map to something new, by calling a conversion
|
||||
## function on each of them. Then return a new #Map of the converted keys and values.
|
||||
##
|
||||
##
|
||||
## >>> Map.map {{ 3.14 => "pi", 1.0 => "one" }} \{ key, value } -> { key:
|
||||
##
|
||||
##
|
||||
## >>> Map.map {[ "", "a", "bc" ]} Str.isEmpty
|
||||
##
|
||||
##
|
||||
## `map` functions like this are common in Roc, and they all work similarly.
|
||||
## See for example #Result.map, #List.map, and #Set.map.
|
||||
map : List before, (before -> after) -> List after
|
||||
|
@ -1,4 +1,4 @@
|
||||
interface Num
|
||||
interface Num2
|
||||
exposes [ Num, neg, abs, add, sub, mul, isOdd, isEven, isPositive, isNegative, isZero ]
|
||||
imports []
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
interface Set
|
||||
exposes [ Set, map, isEmpty ]
|
||||
interface Set2
|
||||
exposes [ empty, isEmpty, len, add, drop, map ]
|
||||
imports []
|
||||
|
||||
|
||||
@ -12,10 +12,14 @@ isEmpty : Set * -> Bool
|
||||
|
||||
len : Set * -> Len
|
||||
|
||||
add : Set 'elem, 'elem -> Set 'elem
|
||||
# TODO: removed `'` from signature because parser does not support it yet
|
||||
# Original signature: `add : Set 'elem, 'elem -> Set 'elem`
|
||||
add : Set elem, elem -> Set elem
|
||||
|
||||
## Drops the given element from the set.
|
||||
drop : Set 'elem, 'elem -> Set 'elem
|
||||
# TODO: removed `'` from signature because parser does not support it yet
|
||||
# Original signature: `drop : Set 'elem, 'elem -> Set 'elem`
|
||||
drop : Set elem, elem -> Set elem
|
||||
|
||||
## Convert each element in the set to something new, by calling a conversion
|
||||
## function on each of them. Then return a new set of the converted values.
|
||||
@ -26,4 +30,6 @@ drop : Set 'elem, 'elem -> Set 'elem
|
||||
##
|
||||
## `map` functions like this are common in Roc, and they all work similarly.
|
||||
## See for example #Result.map, #List.map, and #Map.map.
|
||||
map : Set 'elem, ('before -> 'after) -> Set 'after
|
||||
# TODO: removed `'` from signature because parser does not support it yet
|
||||
# Original signature: `map : Set 'elem, ('before -> 'after) -> Set 'after`
|
||||
map : Set elem, (before -> after) -> Set after
|
||||
|
@ -1,4 +1,6 @@
|
||||
interface Str exposes [ Str, isEmpty, join ] imports []
|
||||
interface Str2
|
||||
exposes [ Str2, decimal, split, isEmpty, startsWith, endsWith, contains, anyGraphemes, allGraphemes, join, joinWith, padGraphemesStart, padGraphemesEnd, graphemes, reverseGraphemes, isCaseInsensitiveEq, isCaseInsensitiveNeq, walkGraphemes, isCapitalized, isAllUppercase, isAllLowercase, toUtf8, toUtf16, toUtf32, walkUtf8, walkUtf16, walkUtf32, walkRevUtf8, walkRevUtf16, walkRevUtf32 ]
|
||||
imports []
|
||||
## Types
|
||||
|
||||
## Dealing with text is a deep topic, so by design, Roc's `Str` module sticks
|
||||
@ -98,7 +100,7 @@ interface Str exposes [ Str, isEmpty, join ] imports []
|
||||
|
||||
## A [Unicode](https://unicode.org) text value.
|
||||
##
|
||||
Str : [ @Str ]
|
||||
Str2 : [ @Str ]
|
||||
|
||||
## Convert
|
||||
|
||||
|
@ -1210,10 +1210,10 @@ pub fn allocate_with_refcount<'a, 'ctx, 'env>(
|
||||
|
||||
// the refcount of a new allocation is initially 1
|
||||
// we assume that the allocation is indeed used (dead variables are eliminated)
|
||||
let ref_count_one = ctx
|
||||
.i64_type()
|
||||
.const_int(crate::llvm::refcounting::REFCOUNT_1 as _, false);
|
||||
builder.build_store(refcount_ptr, ref_count_one);
|
||||
builder.build_store(
|
||||
refcount_ptr,
|
||||
crate::llvm::refcounting::refcount_1(ctx, env.ptr_bytes),
|
||||
);
|
||||
|
||||
// store the value in the pointer
|
||||
builder.build_store(list_element_ptr, value);
|
||||
@ -2388,7 +2388,6 @@ where
|
||||
Layout::Builtin(Builtin::List(MemoryMode::Refcounted, _)) => {
|
||||
// no static guarantees, but all is not lost: we can check the refcount
|
||||
// if it is one, we hold the final reference, and can mutate it in-place!
|
||||
let builder = env.builder;
|
||||
let ctx = env.context;
|
||||
|
||||
let ret_type = basic_type_from_layout(env.arena, ctx, list_layout, env.ptr_bytes);
|
||||
@ -2400,7 +2399,7 @@ where
|
||||
.build_load(refcount_ptr, "get_refcount")
|
||||
.into_int_value();
|
||||
|
||||
let comparison = refcount_is_one_comparison(builder, env.context, refcount);
|
||||
let comparison = refcount_is_one_comparison(env, refcount);
|
||||
|
||||
crate::llvm::build_list::build_basic_phi2(
|
||||
env, parent, comparison, in_place, clone, ret_type,
|
||||
|
@ -1757,8 +1757,7 @@ pub fn allocate_list<'a, 'ctx, 'env>(
|
||||
InPlace::Clone => {
|
||||
// the refcount of a new list is initially 1
|
||||
// we assume that the list is indeed used (dead variables are eliminated)
|
||||
ctx.i64_type()
|
||||
.const_int(crate::llvm::refcounting::REFCOUNT_1 as _, false)
|
||||
crate::llvm::refcounting::refcount_1(ctx, env.ptr_bytes)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -200,7 +200,6 @@ pub fn ptr_int(ctx: &Context, ptr_bytes: u32) -> IntType<'_> {
|
||||
2 => ctx.i16_type(),
|
||||
4 => ctx.i32_type(),
|
||||
8 => ctx.i64_type(),
|
||||
16 => ctx.i128_type(),
|
||||
_ => panic!(
|
||||
"Invalid target: Roc does't support compiling to {}-bit systems.",
|
||||
ptr_bytes * 8
|
||||
|
@ -7,7 +7,6 @@ use crate::llvm::build_list::list_len;
|
||||
use crate::llvm::convert::{basic_type_from_layout, block_of_memory, ptr_int};
|
||||
use bumpalo::collections::Vec;
|
||||
use inkwell::basic_block::BasicBlock;
|
||||
use inkwell::builder::Builder;
|
||||
use inkwell::context::Context;
|
||||
use inkwell::module::Linkage;
|
||||
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue};
|
||||
@ -15,9 +14,21 @@ use inkwell::{AddressSpace, IntPredicate};
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, Layout, MemoryMode};
|
||||
|
||||
pub const REFCOUNT_1: usize = isize::MIN as usize;
|
||||
pub const REFCOUNT_MAX: usize = 0 as usize;
|
||||
|
||||
pub fn refcount_1(ctx: &Context, ptr_bytes: u32) -> IntValue<'_> {
|
||||
match ptr_bytes {
|
||||
1 => ctx.i8_type().const_int(i8::MIN as u64, false),
|
||||
2 => ctx.i16_type().const_int(i16::MIN as u64, false),
|
||||
4 => ctx.i32_type().const_int(i32::MIN as u64, false),
|
||||
8 => ctx.i64_type().const_int(i64::MIN as u64, false),
|
||||
_ => panic!(
|
||||
"Invalid target: Roc does't support compiling to {}-bit systems.",
|
||||
ptr_bytes * 8
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decrement_refcount_layout<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
@ -644,6 +655,7 @@ fn increment_refcount_help<'a, 'ctx, 'env>(
|
||||
) {
|
||||
let builder = env.builder;
|
||||
let ctx = env.context;
|
||||
let refcount_type = ptr_int(ctx, env.ptr_bytes);
|
||||
|
||||
let refcount = env
|
||||
.builder
|
||||
@ -653,12 +665,12 @@ fn increment_refcount_help<'a, 'ctx, 'env>(
|
||||
let max = builder.build_int_compare(
|
||||
IntPredicate::EQ,
|
||||
refcount,
|
||||
ctx.i64_type().const_int(REFCOUNT_MAX as u64, false),
|
||||
refcount_type.const_int(REFCOUNT_MAX as u64, false),
|
||||
"refcount_max_check",
|
||||
);
|
||||
let incremented = builder.build_int_add(
|
||||
refcount,
|
||||
ctx.i64_type().const_int(1 as u64, false),
|
||||
refcount_type.const_int(1 as u64, false),
|
||||
"increment_refcount",
|
||||
);
|
||||
let selected = builder.build_select(max, refcount, incremented, "select_refcount");
|
||||
@ -689,6 +701,7 @@ fn decrement_refcount_help<'a, 'ctx, 'env>(
|
||||
) {
|
||||
let builder = env.builder;
|
||||
let ctx = env.context;
|
||||
let refcount_type = ptr_int(ctx, env.ptr_bytes);
|
||||
|
||||
let refcount = env
|
||||
.builder
|
||||
@ -700,7 +713,7 @@ fn decrement_refcount_help<'a, 'ctx, 'env>(
|
||||
LLVM_SADD_WITH_OVERFLOW_I64,
|
||||
&[
|
||||
refcount.into(),
|
||||
ctx.i64_type().const_int((-1 as i64) as u64, false).into(),
|
||||
refcount_type.const_int((-1 as i64) as u64, true).into(),
|
||||
],
|
||||
)
|
||||
.into_struct_value();
|
||||
@ -738,7 +751,7 @@ fn decrement_refcount_help<'a, 'ctx, 'env>(
|
||||
let max = builder.build_int_compare(
|
||||
IntPredicate::EQ,
|
||||
refcount,
|
||||
ctx.i64_type().const_int(REFCOUNT_MAX as u64, false),
|
||||
refcount_type.const_int(REFCOUNT_MAX as u64, false),
|
||||
"refcount_max_check",
|
||||
);
|
||||
let decremented = builder
|
||||
@ -1137,16 +1150,14 @@ pub fn build_inc_union_help<'a, 'ctx, 'env>(
|
||||
builder.build_return(None);
|
||||
}
|
||||
|
||||
pub fn refcount_is_one_comparison<'ctx>(
|
||||
builder: &Builder<'ctx>,
|
||||
context: &'ctx Context,
|
||||
pub fn refcount_is_one_comparison<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
refcount: IntValue<'ctx>,
|
||||
) -> IntValue<'ctx> {
|
||||
let refcount_one: IntValue<'ctx> = context.i64_type().const_int(REFCOUNT_1 as _, false);
|
||||
builder.build_int_compare(
|
||||
env.builder.build_int_compare(
|
||||
IntPredicate::EQ,
|
||||
refcount,
|
||||
refcount_one,
|
||||
refcount_1(env.context, env.ptr_bytes),
|
||||
"refcount_one_check",
|
||||
)
|
||||
}
|
||||
@ -1171,8 +1182,9 @@ fn get_refcount_ptr<'a, 'ctx, 'env>(
|
||||
layout: &Layout<'a>,
|
||||
ptr: PointerValue<'ctx>,
|
||||
) -> PointerValue<'ctx> {
|
||||
let refcount_type = ptr_int(env.context, env.ptr_bytes);
|
||||
let ptr_as_int =
|
||||
cast_basic_basic(env.builder, ptr.into(), env.context.i64_type().into()).into_int_value();
|
||||
cast_basic_basic(env.builder, ptr.into(), refcount_type.into()).into_int_value();
|
||||
|
||||
get_refcount_ptr_help(env, layout, ptr_as_int)
|
||||
}
|
||||
@ -1192,20 +1204,19 @@ fn get_refcount_ptr_help<'a, 'ctx, 'env>(
|
||||
_ => (env.ptr_bytes as u64).max(value_bytes),
|
||||
};
|
||||
|
||||
// pointer to usize
|
||||
let refcount_type = ptr_int(ctx, env.ptr_bytes);
|
||||
|
||||
// subtract offset, to access the refcount
|
||||
let refcount_ptr = builder.build_int_sub(
|
||||
ptr_as_int,
|
||||
ctx.i64_type().const_int(offset, false),
|
||||
refcount_type.const_int(offset, false),
|
||||
"make_refcount_ptr",
|
||||
);
|
||||
|
||||
// pointer to usize
|
||||
let ptr_bytes = env.ptr_bytes;
|
||||
let int_type = ptr_int(ctx, ptr_bytes);
|
||||
|
||||
builder.build_int_to_ptr(
|
||||
refcount_ptr,
|
||||
int_type.ptr_type(AddressSpace::Generic),
|
||||
refcount_type.ptr_type(AddressSpace::Generic),
|
||||
"get_refcount_ptr",
|
||||
)
|
||||
}
|
||||
|
1660
compiler/load/src/docs.rs
Normal file
1660
compiler/load/src/docs.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -10,4 +10,5 @@
|
||||
// and encouraging shortcuts here creates bad incentives. I would rather temporarily
|
||||
// re-enable this when working on performance optimizations than have it block PRs.
|
||||
#![allow(clippy::large_enum_variant)]
|
||||
pub mod docs;
|
||||
pub mod file;
|
||||
|
1
docs/.gitignore
vendored
Normal file
1
docs/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
@ -13,3 +13,6 @@ serde_json = "1.0.39"
|
||||
serde_derive = "1.0.75"
|
||||
fs_extra = "1.2.0"
|
||||
pulldown-cmark = { version = "0.8", default-features = false }
|
||||
roc_load = { path = "../compiler/load" }
|
||||
roc_builtins = { path = "../compiler/builtins" }
|
||||
roc_collections = { path = "../compiler/collections" }
|
||||
|
186
docs/src/main.rs
186
docs/src/main.rs
@ -7,27 +7,9 @@ extern crate pulldown_cmark;
|
||||
extern crate serde_json;
|
||||
use std::error::Error;
|
||||
use std::fs;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Package {
|
||||
name: String,
|
||||
version: String,
|
||||
docs: String,
|
||||
modules: Vec<Module>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct Module {
|
||||
name: String,
|
||||
docs: String,
|
||||
entries: Vec<ModuleEntry>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct ModuleEntry {
|
||||
name: String,
|
||||
docs: String,
|
||||
}
|
||||
extern crate roc_load;
|
||||
use roc_collections::all::MutMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Template {
|
||||
@ -39,6 +21,12 @@ pub struct Template {
|
||||
module_links: Vec<TemplateLink>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct ModuleEntry {
|
||||
name: String,
|
||||
docs: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct TemplateLink {
|
||||
name: String,
|
||||
@ -53,132 +41,49 @@ pub struct TemplateLinkEntry {
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let package = Package {
|
||||
let std_lib = roc_builtins::std::standard_stdlib();
|
||||
let subs_by_module = MutMap::default();
|
||||
let src_dir = Path::new("../compiler/builtins/docs");
|
||||
let files = vec![
|
||||
PathBuf::from(r"../compiler/builtins/docs/Bool.roc"),
|
||||
PathBuf::from(r"../compiler/builtins/docs/Map.roc"),
|
||||
// Not working
|
||||
// PathBuf::from(r"../compiler/builtins/docs/List.roc"),
|
||||
// Not working
|
||||
// PathBuf::from(r"../compiler/builtins/docs/Num.roc"),
|
||||
PathBuf::from(r"../compiler/builtins/docs/Set.roc"),
|
||||
PathBuf::from(r"../compiler/builtins/docs/Str.roc"),
|
||||
];
|
||||
|
||||
let mut modules_docs = vec![];
|
||||
|
||||
// Load each file is files vector
|
||||
for filename in files {
|
||||
let loaded = roc_load::docs::load(filename, &std_lib, src_dir, subs_by_module.clone())
|
||||
.expect("TODO gracefully handle load failing");
|
||||
modules_docs.push(loaded.module_docs);
|
||||
}
|
||||
|
||||
let package = roc_load::docs::Documentation {
|
||||
name: "roc/builtins".to_string(),
|
||||
version: "1.0.0".to_string(),
|
||||
docs: "Package introduction or README.".to_string(),
|
||||
modules: vec![
|
||||
Module {
|
||||
name: "Str".to_string(),
|
||||
docs: "Module introduction".to_string(),
|
||||
entries: vec![
|
||||
ModuleEntry {
|
||||
name: "Str".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example."
|
||||
.to_string(),
|
||||
},
|
||||
ModuleEntry {
|
||||
name: "isEmpty".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example."
|
||||
.to_string(),
|
||||
},
|
||||
ModuleEntry {
|
||||
name: "append".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example."
|
||||
.to_string(),
|
||||
},
|
||||
ModuleEntry {
|
||||
name: "prepend".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example."
|
||||
.to_string(),
|
||||
},
|
||||
ModuleEntry {
|
||||
name: "concat".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example."
|
||||
.to_string(),
|
||||
},
|
||||
ModuleEntry {
|
||||
name: "join".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example."
|
||||
.to_string(),
|
||||
},
|
||||
ModuleEntry {
|
||||
name: "split".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example."
|
||||
.to_string(),
|
||||
},
|
||||
ModuleEntry {
|
||||
name: "countGraphemes".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example."
|
||||
.to_string(),
|
||||
},
|
||||
ModuleEntry {
|
||||
name: "foldGraphemes".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example."
|
||||
.to_string(),
|
||||
},
|
||||
],
|
||||
},
|
||||
Module {
|
||||
name: "Bool".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example.".to_string(),
|
||||
entries: vec![
|
||||
ModuleEntry {
|
||||
name: "isEq".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example."
|
||||
.to_string(),
|
||||
},
|
||||
ModuleEntry {
|
||||
name: "isNeq".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example."
|
||||
.to_string(),
|
||||
},
|
||||
],
|
||||
},
|
||||
Module {
|
||||
name: "Num".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example.".to_string(),
|
||||
entries: vec![
|
||||
ModuleEntry {
|
||||
name: "add".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example."
|
||||
.to_string(),
|
||||
},
|
||||
ModuleEntry {
|
||||
name: "sub".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example."
|
||||
.to_string(),
|
||||
},
|
||||
ModuleEntry {
|
||||
name: "mul".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example."
|
||||
.to_string(),
|
||||
},
|
||||
],
|
||||
},
|
||||
Module {
|
||||
name: "List".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example.".to_string(),
|
||||
entries: vec![],
|
||||
},
|
||||
Module {
|
||||
name: "Set".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example.".to_string(),
|
||||
entries: vec![],
|
||||
},
|
||||
Module {
|
||||
name: "Map".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example.".to_string(),
|
||||
entries: vec![],
|
||||
},
|
||||
Module {
|
||||
name: "Result".to_string(),
|
||||
docs: "Hello world, this is a **complicated** *very simple* example.".to_string(),
|
||||
entries: vec![],
|
||||
},
|
||||
],
|
||||
modules: modules_docs,
|
||||
};
|
||||
|
||||
// Make sure the directories exists
|
||||
// Remove old build folder
|
||||
fs::remove_dir_all("./build")?;
|
||||
|
||||
// Make sure the output directories exists
|
||||
fs::create_dir_all(format!("./build/{}/{}", package.name, package.version))?;
|
||||
|
||||
// Register handlebar template
|
||||
// Register handlebars template
|
||||
let mut handlebars = handlebars::Handlebars::new();
|
||||
assert!(handlebars
|
||||
.register_template_file("page", "./src/templates/page.hbs")
|
||||
.is_ok());
|
||||
|
||||
let markdown_options = pulldown_cmark::Options::empty();
|
||||
let markdown_options = pulldown_cmark::Options::all();
|
||||
|
||||
// Write each package's module docs
|
||||
for module in &package.modules {
|
||||
@ -198,11 +103,12 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
.into_iter()
|
||||
.map(|entry| {
|
||||
// Convert entry docs from markdown to html
|
||||
let entry_docs_parser =
|
||||
pulldown_cmark::Parser::new_ext(&entry.docs, markdown_options);
|
||||
let mut entry_docs_html: String =
|
||||
String::with_capacity(entry.docs.len() * 3 / 2);
|
||||
pulldown_cmark::html::push_html(&mut entry_docs_html, entry_docs_parser);
|
||||
let mut entry_docs_html: String = String::new();
|
||||
if let Some(docs) = entry.docs {
|
||||
let entry_docs_parser =
|
||||
pulldown_cmark::Parser::new_ext(&docs, markdown_options);
|
||||
pulldown_cmark::html::push_html(&mut entry_docs_html, entry_docs_parser);
|
||||
}
|
||||
|
||||
ModuleEntry {
|
||||
name: entry.name.clone(),
|
||||
|
@ -12,6 +12,10 @@ To run in release mode instead, do:
|
||||
$ cargo run --release run Hello.roc
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you encounter `cannot find -lc++`, run the following for ubuntu `sudo apt install libc++-dev`.
|
||||
|
||||
## Design Notes
|
||||
|
||||
This demonstrates the basic design of hosts: Roc code gets compiled into a pure
|
||||
|
@ -11,3 +11,7 @@ To run in release mode instead, do:
|
||||
```bash
|
||||
$ cargo run --release run Quicksort.roc
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you encounter `cannot find -lc++`, run the following for ubuntu `sudo apt install libc++-dev`.
|
Loading…
Reference in New Issue
Block a user