Merge branch 'str-to-num' of github.com:rtfeldman/roc into str_to_num

This commit is contained in:
Anton-4 2021-12-01 19:43:01 +01:00
commit 2e21fd0cb9
16 changed files with 110 additions and 13 deletions

8
Cargo.lock generated
View file

@ -3374,6 +3374,7 @@ dependencies = [
"roc_module",
"roc_parse",
"roc_region",
"roc_test_utils",
]
[[package]]
@ -3516,9 +3517,7 @@ dependencies = [
name = "roc_parse"
version = "0.1.0"
dependencies = [
"ansi_term",
"bumpalo",
"diff",
"encode_unicode",
"indoc",
"pretty_assertions",
@ -3527,6 +3526,7 @@ dependencies = [
"roc_collections",
"roc_module",
"roc_region",
"roc_test_utils",
]
[[package]]
@ -3591,6 +3591,10 @@ dependencies = [
name = "roc_std"
version = "0.1.0"
[[package]]
name = "roc_test_utils"
version = "0.1.0"
[[package]]
name = "roc_types"
version = "0.1.0"

View file

@ -32,6 +32,7 @@ members = [
"code_markup",
"reporting",
"roc_std",
"test_utils",
"utils",
"docs",
"linker",

View file

@ -47,7 +47,7 @@ install-zig-llvm-valgrind-clippy-rustfmt:
copy-dirs:
FROM +install-zig-llvm-valgrind-clippy-rustfmt
COPY --dir cli cli_utils compiler docs editor ast code_markup utils reporting roc_std vendor examples linker Cargo.toml Cargo.lock version.txt ./
COPY --dir cli cli_utils compiler docs editor ast code_markup utils test_utils reporting roc_std vendor examples linker Cargo.toml Cargo.lock version.txt ./
test-zig:
FROM +install-zig-llvm-valgrind-clippy-rustfmt

View file

@ -94,6 +94,7 @@ comptime {
inline for (INTEGERS) |T| {
num.exportPow(T, ROC_BUILTINS ++ "." ++ NUM ++ ".pow_int.");
num.exportDivCeil(T, ROC_BUILTINS ++ "." ++ NUM ++ ".div_ceil.");
num.exportParseInt(T, ROC_BUILTINS ++ "." ++ NUM ++ ".to_int.");
}
inline for (FLOATS) |T| {

View file

@ -2,6 +2,42 @@ const std = @import("std");
const always_inline = std.builtin.CallOptions.Modifier.always_inline;
const math = std.math;
const RocList = @import("list.zig").RocList;
const RocStr = @import("str.zig").RocStr;
pub fn NumParseResult(comptime T: type) type {
return extern struct {
errorcode: u8, // 0 indicates success
value: T,
};
}
pub fn exportParseInt(comptime T: type, comptime name: []const u8) void {
comptime var f = struct {
fn func(input: T, buf: RocStr) callconv(.C) NumParseResult(T) {
// a radix of 0 will make zig determine the radix from the frefix:
// * A prefix of "0b" implies radix=2,
// * A prefix of "0o" implies radix=8,
// * A prefix of "0x" implies radix=16,
// * Otherwise radix=10 is assumed.
const radix = 0;
if (std.fmt.parseInt(T, buf.asSlice(), radix)) |success| {
return .{ .errorcode = 0, .value = success };
} else |err| {
return .{ .errorcode = 1, .value = 0 };
}
}
}.func;
@export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong });
}
pub fn exportParseFloat(comptime T: type, comptime name: []const u8) void {
comptime var f = struct {
fn func(input: T, buf: []const u8) callconv(.C) bool {
return std.fmt.parseFloat(T, buf);
}
}.func;
@export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong });
}
pub fn exportPow(comptime T: type, comptime name: []const u8) void {
comptime var f = struct {

View file

@ -242,6 +242,9 @@ pub const STR_ENDS_WITH: &str = "roc_builtins.str.ends_with";
pub const STR_NUMBER_OF_BYTES: &str = "roc_builtins.str.number_of_bytes";
pub const STR_FROM_INT: IntrinsicName = int_intrinsic!("roc_builtins.str.from_int");
pub const STR_FROM_FLOAT: &str = "roc_builtins.str.from_float";
pub const STR_TO_INT: IntrinsicName = int_intrinsic!("roc_builtins.str.to_int");
pub const STR_TO_FLOAT: IntrinsicName = float_intrinsic!("roc_builtins.str.to_float");
pub const STR_TO_DECIMAL: &str = "roc_builtins.str.to_decimal";
pub const STR_EQUAL: &str = "roc_builtins.str.equal";
pub const STR_TO_UTF8: &str = "roc_builtins.str.to_utf8";
pub const STR_FROM_UTF8: &str = "roc_builtins.str.from_utf8";

View file

@ -15,3 +15,4 @@ bumpalo = { version = "3.8.0", features = ["collections"] }
[dev-dependencies]
pretty_assertions = "1.0.0"
indoc = "1.0.3"
roc_test_utils = { path = "../../test_utils" }

View file

@ -1098,6 +1098,7 @@ fn sub_expr_requests_parens(expr: &Expr<'_>) -> bool {
BinOp::Pizza | BinOp::Assignment | BinOp::HasType | BinOp::Backpassing => false,
})
}
Expr::If(_, _) => true,
_ => false,
}
}

View file

@ -1,6 +1,4 @@
#[macro_use]
extern crate pretty_assertions;
#[macro_use]
extern crate indoc;
extern crate bumpalo;
extern crate roc_fmt;
@ -14,6 +12,7 @@ mod test_fmt {
use roc_fmt::module::fmt_module;
use roc_parse::module::{self, module_defs};
use roc_parse::parser::{Parser, State};
use roc_test_utils::assert_multiline_str_eq;
fn expr_formats_to(input: &str, expected: &str) {
let arena = Bump::new();
@ -26,7 +25,7 @@ mod test_fmt {
actual.format_with_options(&mut buf, Parens::NotNeeded, Newlines::Yes, 0);
assert_eq!(buf, expected)
assert_multiline_str_eq!(expected, buf.as_str())
}
Err(error) => panic!("Unexpected parse failure when parsing this for formatting:\n\n{}\n\nParse error was:\n\n{:?}\n\n", input, error)
};
@ -56,7 +55,7 @@ mod test_fmt {
Err(error) => panic!("Unexpected parse failure when parsing this for defs formatting:\n\n{:?}\n\nParse error was:\n\n{:?}\n\n", src, error)
}
assert_eq!(buf, expected)
assert_multiline_str_eq!(expected, buf.as_str())
}
Err(error) => panic!("Unexpected parse failure when parsing this for module header formatting:\n\n{:?}\n\nParse error was:\n\n{:?}\n\n", src, error)
};
@ -2311,6 +2310,15 @@ mod test_fmt {
));
}
#[test]
fn binop_if() {
expr_formats_same(indoc!(
r#"
5 * (if x > 0 then 1 else 2)
"#
));
}
// UNARY OP
#[test]

View file

@ -5268,6 +5268,23 @@ fn run_low_level<'a, 'ctx, 'env>(
str_ends_with(env, scope, args[0], args[1])
}
StrToNum => {
debug_assert_eq!(args.len(), 1);
let (string, _string_layout) = load_symbol_and_layout(scope, &args[0]);
// match on the return layout to figure out which zig builtin we need
let intrinsic = match layout {
Layout::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[*int_width],
Layout::Builtin(Builtin::Float(float_width)) => {
&bitcode::STR_TO_FLOAT[*float_width]
}
Layout::Builtin(Builtin::Decimal) => bitcode::STR_TO_DECIMAL,
_ => unreachable!(),
};
call_bitcode_fn(env, &[string], intrinsic)
}
StrFromInt => {
// Str.fromInt : Int -> Str
debug_assert_eq!(args.len(), 1);

View file

@ -38,6 +38,7 @@ pub fn decode_low_level<'a>(
StrEndsWith => return BuiltinCall(bitcode::STR_ENDS_WITH),
StrSplit => return NotImplemented, // needs Array
StrCountGraphemes => return NotImplemented, // test needs Array
StrToNum => return NotImplemented, // choose builtin based on storage size
StrFromInt => return NotImplemented, // choose builtin based on storage size
StrFromUtf8 => return NotImplemented, // needs Array
StrTrimLeft => return BuiltinCall(bitcode::STR_TRIM_LEFT),

View file

@ -13,6 +13,7 @@ pub enum LowLevel {
StrEndsWith,
StrSplit,
StrCountGraphemes,
StrToNum,
StrFromInt,
StrFromUtf8,
StrFromUtf8Range,

View file

@ -17,5 +17,4 @@ pretty_assertions = "1.0.0"
indoc = "1.0.3"
quickcheck = "1.0.3"
quickcheck_macros = "1.0.0"
diff = "0.1.12"
ansi_term = "0.12.1"
roc_test_utils = { path = "../../test_utils" }

View file

@ -23,6 +23,7 @@ mod test_parse {
use roc_parse::parser::{Parser, State, SyntaxError};
use roc_parse::test_helpers::parse_expr_with;
use roc_region::all::{Located, Region};
use roc_test_utils::assert_multiline_str_eq;
use std::{f64, i64};
macro_rules! snapshot_tests {
@ -254,10 +255,7 @@ mod test_parse {
} else {
let expected_result = std::fs::read_to_string(&result_path).unwrap();
// TODO: do a diff over the "real" content of these strings, rather than
// the debug-formatted content. As is, we get an ugly single-line diff
// from pretty_assertions
assert_eq!(expected_result, actual_result);
assert_multiline_str_eq!(expected_result, actual_result);
}
}

11
test_utils/Cargo.toml Normal file
View file

@ -0,0 +1,11 @@
[package]
name = "roc_test_utils"
version = "0.1.0"
authors = ["The Roc Contributors"]
license = "UPL-1.0"
edition = "2018"
description = "Utility functions used all over the code base."
[dependencies]
[dev-dependencies]

15
test_utils/src/lib.rs Normal file
View file

@ -0,0 +1,15 @@
#[derive(PartialEq)]
pub struct DebugAsDisplay<T>(pub T);
impl<T: std::fmt::Display> std::fmt::Debug for DebugAsDisplay<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
#[macro_export]
macro_rules! assert_multiline_str_eq {
($a:expr, $b:expr) => {
assert_eq!($crate::DebugAsDisplay($a), $crate::DebugAsDisplay($b))
};
}