mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 16:21:11 +00:00
Merge branch 'type-to-var-tco' into builtins-in-roc
This commit is contained in:
commit
47a1e5f816
6 changed files with 154 additions and 71 deletions
|
@ -16,7 +16,6 @@ use roc_types::types::{
|
||||||
gather_fields_unsorted_iter, AliasKind, Category, ErrorType, PatternCategory,
|
gather_fields_unsorted_iter, AliasKind, Category, ErrorType, PatternCategory,
|
||||||
};
|
};
|
||||||
use roc_unify::unify::{unify, Mode, Unified::*};
|
use roc_unify::unify::{unify, Mode, Unified::*};
|
||||||
use std::collections::hash_map::Entry;
|
|
||||||
|
|
||||||
// Type checking system adapted from Elm by Evan Czaplicki, BSD-3-Clause Licensed
|
// Type checking system adapted from Elm by Evan Czaplicki, BSD-3-Clause Licensed
|
||||||
// https://github.com/elm/compiler
|
// https://github.com/elm/compiler
|
||||||
|
@ -915,6 +914,25 @@ impl RegisterVariable {
|
||||||
_ => Deferred,
|
_ => Deferred,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn with_stack<'a>(
|
||||||
|
subs: &mut Subs,
|
||||||
|
rank: Rank,
|
||||||
|
pools: &mut Pools,
|
||||||
|
arena: &'_ bumpalo::Bump,
|
||||||
|
typ: &'a Type,
|
||||||
|
stack: &mut bumpalo::collections::Vec<'_, TypeToVar<'a>>,
|
||||||
|
) -> Variable {
|
||||||
|
match Self::from_type(subs, rank, pools, arena, typ) {
|
||||||
|
Self::Direct(var) => var,
|
||||||
|
Self::Deferred => {
|
||||||
|
let var = subs.fresh_unnamed_flex_var();
|
||||||
|
stack.push(TypeToVar::Defer(typ, var));
|
||||||
|
var
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -1046,7 +1064,8 @@ fn type_to_variable<'a>(
|
||||||
// If hit, try to turn the value into an EmptyTagUnion in canonicalization
|
// If hit, try to turn the value into an EmptyTagUnion in canonicalization
|
||||||
debug_assert!(!tags.is_empty() || !ext.is_empty_tag_union());
|
debug_assert!(!tags.is_empty() || !ext.is_empty_tag_union());
|
||||||
|
|
||||||
let (union_tags, ext) = type_to_union_tags(subs, rank, pools, arena, tags, ext);
|
let (union_tags, ext) =
|
||||||
|
type_to_union_tags(subs, rank, pools, arena, tags, ext, &mut stack);
|
||||||
let content = Content::Structure(FlatType::TagUnion(union_tags, ext));
|
let content = Content::Structure(FlatType::TagUnion(union_tags, ext));
|
||||||
|
|
||||||
register_with_known_var(subs, destination, rank, pools, content)
|
register_with_known_var(subs, destination, rank, pools, content)
|
||||||
|
@ -1076,7 +1095,8 @@ fn type_to_variable<'a>(
|
||||||
// If hit, try to turn the value into an EmptyTagUnion in canonicalization
|
// If hit, try to turn the value into an EmptyTagUnion in canonicalization
|
||||||
debug_assert!(!tags.is_empty() || !ext.is_empty_tag_union());
|
debug_assert!(!tags.is_empty() || !ext.is_empty_tag_union());
|
||||||
|
|
||||||
let (union_tags, ext) = type_to_union_tags(subs, rank, pools, arena, tags, ext);
|
let (union_tags, ext) =
|
||||||
|
type_to_union_tags(subs, rank, pools, arena, tags, ext, &mut stack);
|
||||||
let content =
|
let content =
|
||||||
Content::Structure(FlatType::RecursiveTagUnion(*rec_var, union_tags, ext));
|
Content::Structure(FlatType::RecursiveTagUnion(*rec_var, union_tags, ext));
|
||||||
|
|
||||||
|
@ -1132,7 +1152,7 @@ fn type_to_variable<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
let alias_variable = if let Symbol::RESULT_RESULT = *symbol {
|
let alias_variable = if let Symbol::RESULT_RESULT = *symbol {
|
||||||
roc_result_to_var(subs, rank, pools, arena, actual)
|
roc_result_to_var(subs, rank, pools, arena, actual, &mut stack)
|
||||||
} else {
|
} else {
|
||||||
helper!(actual)
|
helper!(actual)
|
||||||
};
|
};
|
||||||
|
@ -1212,8 +1232,9 @@ fn roc_result_to_var<'a>(
|
||||||
subs: &mut Subs,
|
subs: &mut Subs,
|
||||||
rank: Rank,
|
rank: Rank,
|
||||||
pools: &mut Pools,
|
pools: &mut Pools,
|
||||||
arena: &'a bumpalo::Bump,
|
arena: &'_ bumpalo::Bump,
|
||||||
result_type: &Type,
|
result_type: &'a Type,
|
||||||
|
stack: &mut bumpalo::collections::Vec<'_, TypeToVar<'a>>,
|
||||||
) -> Variable {
|
) -> Variable {
|
||||||
match result_type {
|
match result_type {
|
||||||
Type::TagUnion(tags, ext) => {
|
Type::TagUnion(tags, ext) => {
|
||||||
|
@ -1225,8 +1246,10 @@ fn roc_result_to_var<'a>(
|
||||||
debug_assert_eq!(ok, &subs.tag_names[1]);
|
debug_assert_eq!(ok, &subs.tag_names[1]);
|
||||||
|
|
||||||
if let ([err_type], [ok_type]) = (err_args.as_slice(), ok_args.as_slice()) {
|
if let ([err_type], [ok_type]) = (err_args.as_slice(), ok_args.as_slice()) {
|
||||||
let err_var = type_to_variable(subs, rank, pools, arena, err_type);
|
let err_var =
|
||||||
let ok_var = type_to_variable(subs, rank, pools, arena, ok_type);
|
RegisterVariable::with_stack(subs, rank, pools, arena, err_type, stack);
|
||||||
|
let ok_var =
|
||||||
|
RegisterVariable::with_stack(subs, rank, pools, arena, ok_type, stack);
|
||||||
|
|
||||||
let start = subs.variables.len() as u32;
|
let start = subs.variables.len() as u32;
|
||||||
let err_slice = SubsSlice::new(start, 1);
|
let err_slice = SubsSlice::new(start, 1);
|
||||||
|
@ -1317,16 +1340,16 @@ fn sort_and_deduplicate<T>(tag_vars: &mut bumpalo::collections::Vec<(TagName, T)
|
||||||
fn find_tag_name_run<T>(slice: &[(TagName, T)], subs: &mut Subs) -> Option<SubsSlice<TagName>> {
|
fn find_tag_name_run<T>(slice: &[(TagName, T)], subs: &mut Subs) -> Option<SubsSlice<TagName>> {
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
let tag_name = slice.get(0)?.0.clone();
|
let tag_name = &slice.get(0)?.0;
|
||||||
|
|
||||||
let mut result = None;
|
let mut result = None;
|
||||||
|
|
||||||
// the `SubsSlice<TagName>` that inserting `slice` into subs would give
|
// the `SubsSlice<TagName>` that inserting `slice` into subs would give
|
||||||
let bigger_slice = SubsSlice::new(subs.tag_names.len() as _, slice.len() as _);
|
let bigger_slice = SubsSlice::new(subs.tag_names.len() as _, slice.len() as _);
|
||||||
|
|
||||||
match subs.tag_name_cache.entry(tag_name) {
|
match subs.tag_name_cache.get_mut(tag_name) {
|
||||||
Entry::Occupied(mut occupied) => {
|
Some(occupied) => {
|
||||||
let subs_slice = *occupied.get();
|
let subs_slice = *occupied;
|
||||||
|
|
||||||
let prefix_slice = SubsSlice::new(subs_slice.start, slice.len() as _);
|
let prefix_slice = SubsSlice::new(subs_slice.start, slice.len() as _);
|
||||||
|
|
||||||
|
@ -1360,12 +1383,12 @@ fn find_tag_name_run<T>(slice: &[(TagName, T)], subs: &mut Subs) -> Option<SubsS
|
||||||
}
|
}
|
||||||
Ordering::Greater => {
|
Ordering::Greater => {
|
||||||
// switch to the bigger slice that is not inserted yet, but will be soon
|
// switch to the bigger slice that is not inserted yet, but will be soon
|
||||||
occupied.insert(bigger_slice);
|
*occupied = bigger_slice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Entry::Vacant(vacant) => {
|
None => {
|
||||||
vacant.insert(bigger_slice);
|
subs.tag_name_cache.push(tag_name, bigger_slice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1377,8 +1400,9 @@ fn insert_tags_fast_path<'a>(
|
||||||
subs: &mut Subs,
|
subs: &mut Subs,
|
||||||
rank: Rank,
|
rank: Rank,
|
||||||
pools: &mut Pools,
|
pools: &mut Pools,
|
||||||
arena: &'a bumpalo::Bump,
|
arena: &'_ bumpalo::Bump,
|
||||||
tags: &[(TagName, Vec<Type>)],
|
tags: &'a [(TagName, Vec<Type>)],
|
||||||
|
stack: &mut bumpalo::collections::Vec<'_, TypeToVar<'a>>,
|
||||||
) -> UnionTags {
|
) -> UnionTags {
|
||||||
let new_variable_slices = SubsSlice::reserve_variable_slices(subs, tags.len());
|
let new_variable_slices = SubsSlice::reserve_variable_slices(subs, tags.len());
|
||||||
|
|
||||||
|
@ -1391,7 +1415,8 @@ fn insert_tags_fast_path<'a>(
|
||||||
let new_variables = VariableSubsSlice::reserve_into_subs(subs, arguments.len());
|
let new_variables = VariableSubsSlice::reserve_into_subs(subs, arguments.len());
|
||||||
let it = (new_variables.indices()).zip(arguments);
|
let it = (new_variables.indices()).zip(arguments);
|
||||||
for (target_index, argument) in it {
|
for (target_index, argument) in it {
|
||||||
let var = type_to_variable(subs, rank, pools, arena, argument);
|
let var =
|
||||||
|
RegisterVariable::with_stack(subs, rank, pools, arena, argument, stack);
|
||||||
subs.variables[target_index] = var;
|
subs.variables[target_index] = var;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1412,7 +1437,8 @@ fn insert_tags_fast_path<'a>(
|
||||||
let new_variables = VariableSubsSlice::reserve_into_subs(subs, arguments.len());
|
let new_variables = VariableSubsSlice::reserve_into_subs(subs, arguments.len());
|
||||||
let it = (new_variables.indices()).zip(arguments);
|
let it = (new_variables.indices()).zip(arguments);
|
||||||
for (target_index, argument) in it {
|
for (target_index, argument) in it {
|
||||||
let var = type_to_variable(subs, rank, pools, arena, argument);
|
let var =
|
||||||
|
RegisterVariable::with_stack(subs, rank, pools, arena, argument, stack);
|
||||||
subs.variables[target_index] = var;
|
subs.variables[target_index] = var;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1429,15 +1455,16 @@ fn insert_tags_slow_path<'a>(
|
||||||
subs: &mut Subs,
|
subs: &mut Subs,
|
||||||
rank: Rank,
|
rank: Rank,
|
||||||
pools: &mut Pools,
|
pools: &mut Pools,
|
||||||
arena: &'a bumpalo::Bump,
|
arena: &'_ bumpalo::Bump,
|
||||||
tags: &[(TagName, Vec<Type>)],
|
tags: &'a [(TagName, Vec<Type>)],
|
||||||
mut tag_vars: bumpalo::collections::Vec<(TagName, VariableSubsSlice)>,
|
mut tag_vars: bumpalo::collections::Vec<(TagName, VariableSubsSlice)>,
|
||||||
|
stack: &mut bumpalo::collections::Vec<'_, TypeToVar<'a>>,
|
||||||
) -> UnionTags {
|
) -> UnionTags {
|
||||||
for (tag, tag_argument_types) in tags {
|
for (tag, tag_argument_types) in tags {
|
||||||
let new_slice = VariableSubsSlice::reserve_into_subs(subs, tag_argument_types.len());
|
let new_slice = VariableSubsSlice::reserve_into_subs(subs, tag_argument_types.len());
|
||||||
|
|
||||||
for (i, arg) in (new_slice.indices()).zip(tag_argument_types) {
|
for (i, arg) in (new_slice.indices()).zip(tag_argument_types) {
|
||||||
let var = type_to_variable(subs, rank, pools, arena, arg);
|
let var = RegisterVariable::with_stack(subs, rank, pools, arena, arg, stack);
|
||||||
subs.variables[i] = var;
|
subs.variables[i] = var;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1453,39 +1480,39 @@ fn type_to_union_tags<'a>(
|
||||||
subs: &mut Subs,
|
subs: &mut Subs,
|
||||||
rank: Rank,
|
rank: Rank,
|
||||||
pools: &mut Pools,
|
pools: &mut Pools,
|
||||||
arena: &'a bumpalo::Bump,
|
arena: &'_ bumpalo::Bump,
|
||||||
tags: &[(TagName, Vec<Type>)],
|
tags: &'a [(TagName, Vec<Type>)],
|
||||||
ext: &Type,
|
ext: &'a Type,
|
||||||
|
stack: &mut bumpalo::collections::Vec<'_, TypeToVar<'a>>,
|
||||||
) -> (UnionTags, Variable) {
|
) -> (UnionTags, Variable) {
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
|
|
||||||
let sorted = tags.len() == 1 || sorted_no_duplicates(tags);
|
let sorted = tags.len() == 1 || sorted_no_duplicates(tags);
|
||||||
|
|
||||||
if ext.is_empty_tag_union() {
|
if ext.is_empty_tag_union() {
|
||||||
let ext = type_to_variable(subs, rank, pools, arena, &Type::EmptyTagUnion);
|
let ext = Variable::EMPTY_TAG_UNION;
|
||||||
// let ext = Variable::EMPTY_TAG_UNION;
|
|
||||||
|
|
||||||
let union_tags = if sorted {
|
let union_tags = if sorted {
|
||||||
insert_tags_fast_path(subs, rank, pools, arena, tags)
|
insert_tags_fast_path(subs, rank, pools, arena, tags, stack)
|
||||||
} else {
|
} else {
|
||||||
let tag_vars = Vec::with_capacity_in(tags.len(), arena);
|
let tag_vars = Vec::with_capacity_in(tags.len(), arena);
|
||||||
insert_tags_slow_path(subs, rank, pools, arena, tags, tag_vars)
|
insert_tags_slow_path(subs, rank, pools, arena, tags, tag_vars, stack)
|
||||||
};
|
};
|
||||||
|
|
||||||
(union_tags, ext)
|
(union_tags, ext)
|
||||||
} else {
|
} else {
|
||||||
let mut tag_vars = Vec::with_capacity_in(tags.len(), arena);
|
let mut tag_vars = Vec::with_capacity_in(tags.len(), arena);
|
||||||
|
|
||||||
let temp_ext_var = type_to_variable(subs, rank, pools, arena, ext);
|
let temp_ext_var = RegisterVariable::with_stack(subs, rank, pools, arena, ext, stack);
|
||||||
let (it, ext) =
|
let (it, ext) =
|
||||||
roc_types::types::gather_tags_unsorted_iter(subs, UnionTags::default(), temp_ext_var);
|
roc_types::types::gather_tags_unsorted_iter(subs, UnionTags::default(), temp_ext_var);
|
||||||
|
|
||||||
tag_vars.extend(it.map(|(n, v)| (n.clone(), v)));
|
tag_vars.extend(it.map(|(n, v)| (n.clone(), v)));
|
||||||
|
|
||||||
let union_tags = if tag_vars.is_empty() && sorted {
|
let union_tags = if tag_vars.is_empty() && sorted {
|
||||||
insert_tags_fast_path(subs, rank, pools, arena, tags)
|
insert_tags_fast_path(subs, rank, pools, arena, tags, stack)
|
||||||
} else {
|
} else {
|
||||||
insert_tags_slow_path(subs, rank, pools, arena, tags, tag_vars)
|
insert_tags_slow_path(subs, rank, pools, arena, tags, tag_vars, stack)
|
||||||
};
|
};
|
||||||
|
|
||||||
(union_tags, ext)
|
(union_tags, ext)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::types::{name_type_var, AliasKind, ErrorType, Problem, RecordField, TypeExt};
|
use crate::types::{name_type_var, AliasKind, ErrorType, Problem, RecordField, TypeExt};
|
||||||
use roc_collections::all::{ImMap, ImSet, MutMap, MutSet, SendMap};
|
use roc_collections::all::{ImMap, ImSet, MutSet, SendMap};
|
||||||
use roc_module::ident::{Lowercase, TagName, Uppercase};
|
use roc_module::ident::{Lowercase, TagName, Uppercase};
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -68,7 +68,49 @@ pub struct Subs {
|
||||||
pub field_names: Vec<Lowercase>,
|
pub field_names: Vec<Lowercase>,
|
||||||
pub record_fields: Vec<RecordField<()>>,
|
pub record_fields: Vec<RecordField<()>>,
|
||||||
pub variable_slices: Vec<VariableSubsSlice>,
|
pub variable_slices: Vec<VariableSubsSlice>,
|
||||||
pub tag_name_cache: MutMap<TagName, SubsSlice<TagName>>,
|
pub tag_name_cache: TagNameCache,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct TagNameCache {
|
||||||
|
globals: Vec<Uppercase>,
|
||||||
|
globals_slices: Vec<SubsSlice<TagName>>,
|
||||||
|
/// Currently private tags and closure tags; in the future just closure tags
|
||||||
|
symbols: Vec<Symbol>,
|
||||||
|
symbols_slices: Vec<SubsSlice<TagName>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TagNameCache {
|
||||||
|
pub fn get_mut(&mut self, tag_name: &TagName) -> Option<&mut SubsSlice<TagName>> {
|
||||||
|
match tag_name {
|
||||||
|
TagName::Global(uppercase) => {
|
||||||
|
// force into block
|
||||||
|
match self.globals.iter().position(|u| u == uppercase) {
|
||||||
|
Some(index) => Some(&mut self.globals_slices[index]),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TagName::Private(symbol) | TagName::Closure(symbol) => {
|
||||||
|
match self.symbols.iter().position(|s| s == symbol) {
|
||||||
|
Some(index) => Some(&mut self.symbols_slices[index]),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, tag_name: &TagName, slice: SubsSlice<TagName>) {
|
||||||
|
match tag_name {
|
||||||
|
TagName::Global(uppercase) => {
|
||||||
|
self.globals.push(uppercase.clone());
|
||||||
|
self.globals_slices.push(slice);
|
||||||
|
}
|
||||||
|
TagName::Private(symbol) | TagName::Closure(symbol) => {
|
||||||
|
self.symbols.push(*symbol);
|
||||||
|
self.symbols_slices.push(slice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Subs {
|
impl Default for Subs {
|
||||||
|
@ -1248,7 +1290,7 @@ impl Subs {
|
||||||
// store an empty slice at the first position
|
// store an empty slice at the first position
|
||||||
// used for "TagOrFunction"
|
// used for "TagOrFunction"
|
||||||
variable_slices: vec![VariableSubsSlice::default()],
|
variable_slices: vec![VariableSubsSlice::default()],
|
||||||
tag_name_cache: MutMap::default(),
|
tag_name_cache: TagNameCache::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE the utable does not (currently) have a with_capacity; using this as the next-best thing
|
// NOTE the utable does not (currently) have a with_capacity; using this as the next-best thing
|
||||||
|
|
|
@ -43,16 +43,20 @@ section.history {
|
||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
#history-text .input {
|
.history-item {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
.history-item .input {
|
||||||
|
margin: 0;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
#history-text .output {
|
.history-item .output {
|
||||||
margin-bottom: 16px;
|
margin: 0;
|
||||||
}
|
}
|
||||||
#history-text .output-ok {
|
.history-item .output-ok {
|
||||||
color: #0f8;
|
color: #0f8;
|
||||||
}
|
}
|
||||||
#history-text .output-error {
|
.history-item .output-error {
|
||||||
color: #f00;
|
color: #f00;
|
||||||
}
|
}
|
||||||
.code {
|
.code {
|
||||||
|
@ -64,9 +68,7 @@ section.source {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
section.source textarea {
|
section.source textarea {
|
||||||
height: 32px;
|
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,9 @@ function onInputKeyup(event) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENTER:
|
case ENTER:
|
||||||
onInputChange({ target: repl.elemSourceInput });
|
if (!event.shiftKey) {
|
||||||
|
onInputChange({ target: repl.elemSourceInput });
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -168,12 +170,13 @@ function createHistoryEntry(inputText) {
|
||||||
const historyIndex = repl.inputHistory.length;
|
const historyIndex = repl.inputHistory.length;
|
||||||
repl.inputHistory.push(inputText);
|
repl.inputHistory.push(inputText);
|
||||||
|
|
||||||
const inputElem = document.createElement("div");
|
const inputElem = document.createElement("pre");
|
||||||
inputElem.textContent = "> " + inputText;
|
inputElem.textContent = inputText;
|
||||||
inputElem.classList.add("input");
|
inputElem.classList.add("input");
|
||||||
|
|
||||||
const historyItem = document.createElement("div");
|
const historyItem = document.createElement("div");
|
||||||
historyItem.appendChild(inputElem);
|
historyItem.appendChild(inputElem);
|
||||||
|
historyItem.classList.add("history-item");
|
||||||
|
|
||||||
repl.elemHistory.appendChild(historyItem);
|
repl.elemHistory.appendChild(historyItem);
|
||||||
repl.elemHistory.scrollTop = repl.elemHistory.scrollHeight;
|
repl.elemHistory.scrollTop = repl.elemHistory.scrollHeight;
|
||||||
|
@ -182,7 +185,7 @@ function createHistoryEntry(inputText) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateHistoryEntry(index, ok, outputText) {
|
function updateHistoryEntry(index, ok, outputText) {
|
||||||
const outputElem = document.createElement("div");
|
const outputElem = document.createElement("pre");
|
||||||
outputElem.textContent = outputText;
|
outputElem.textContent = outputText;
|
||||||
outputElem.classList.add("output");
|
outputElem.classList.add("output");
|
||||||
outputElem.classList.add(ok ? "output-ok" : "output-error");
|
outputElem.classList.add(ok ? "output-ok" : "output-error");
|
||||||
|
|
|
@ -1,29 +1,33 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Roc REPL</title>
|
||||||
|
<link rel="stylesheet" href="/repl.css" />
|
||||||
|
</head>
|
||||||
|
|
||||||
<head>
|
<body>
|
||||||
<title>Roc REPL</title>
|
<div class="body-wrapper">
|
||||||
<link rel="stylesheet" href="/repl.css" />
|
<section class="text">
|
||||||
</head>
|
<h1>The rockin' Roc REPL</h1>
|
||||||
|
</section>
|
||||||
|
|
||||||
<body>
|
<section class="history">
|
||||||
<div class="body-wrapper">
|
<div class="scroll-wrap">
|
||||||
<section class="text">
|
<div id="history-text" class="scroll code"></div>
|
||||||
<h1>The rockin' Roc REPL</h1>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="history">
|
|
||||||
<div class="scroll-wrap">
|
|
||||||
<div id="history-text" class="scroll code"></div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="source">
|
|
||||||
<textarea autofocus id="source-input" class="code" placeholder="Type some Roc code and press Enter"></textarea>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
<script type="module" src="/repl.js"></script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
|
<section class="source">
|
||||||
|
<textarea
|
||||||
|
rows="5"
|
||||||
|
autofocus
|
||||||
|
id="source-input"
|
||||||
|
class="code"
|
||||||
|
placeholder="Type some Roc code and press Enter. (Use Shift+Enter for multi-line input)"
|
||||||
|
></textarea>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<script type="module" src="/repl.js"></script>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
11
www/build.sh
11
www/build.sh
|
@ -12,13 +12,18 @@ rm -rf build/
|
||||||
cp -r public/ build/
|
cp -r public/ build/
|
||||||
|
|
||||||
pushd build
|
pushd build
|
||||||
|
|
||||||
# grab the source code and copy it to Netlify's server; if it's not there, fail the build.
|
# grab the source code and copy it to Netlify's server; if it's not there, fail the build.
|
||||||
wget https://github.com/rtfeldman/elm-css/files/8037422/roc-source-code.zip
|
wget https://github.com/rtfeldman/elm-css/files/8037422/roc-source-code.zip
|
||||||
|
|
||||||
# grab the pre-compiled REPL and copy it to Netlify's server; if it's not there, fail the build.
|
# grab the pre-compiled REPL and copy it to Netlify's server; if it's not there, fail the build.
|
||||||
wget https://github.com/brian-carroll/mock-repl/files/8167902/roc_repl_wasm.tar.gz
|
wget https://github.com/brian-carroll/mock-repl/archive/refs/heads/deploy.zip
|
||||||
tar xzvf roc_repl_wasm.tar.gz
|
unzip deploy.zip
|
||||||
rm roc_repl_wasm.tar.gz
|
mv mock-repl-deploy/* .
|
||||||
|
rmdir mock-repl-deploy
|
||||||
|
rm deploy.zip
|
||||||
|
|
||||||
|
# Copy REPL webpage source files
|
||||||
cp -r ../../repl_www/public/* .
|
cp -r ../../repl_www/public/* .
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue