Follow Zig conventions; Update zig bitcode export fn names; Update rust

to use bitcode fn name consts;
This commit is contained in:
Jared Ramirez 2020-10-29 15:43:22 -07:00
parent de36c8e270
commit 08b78e9c9b
3 changed files with 213 additions and 189 deletions

View file

@ -2,40 +2,48 @@ const std = @import("std");
const math = std.math; const math = std.math;
const expect = std.testing.expect; const expect = std.testing.expect;
export fn atan_(num: f64) f64 { const roc_builtins_namespace = "roc_builtins";
const math_namespace = roc_builtins_namespace ++ ".math";
const str_namespace = roc_builtins_namespace ++ ".str";
comptime { @export(atan, .{ .name = math_namespace ++ ".atan", .linkage = .Strong }); }
fn atan(num: f64) callconv(.C) f64 {
return math.atan(num); return math.atan(num);
} }
export fn is_finite_(num: f64) bool { comptime { @export(isFinite, .{ .name = math_namespace ++ ".is_finite", .linkage = .Strong }); }
fn isFinite(num: f64) callconv(.C) bool {
return math.isFinite(num); return math.isFinite(num);
} }
export fn pow_int_(base: i64, exp: i64) i64 { comptime { @export(powInt, .{ .name = math_namespace ++ ".pow_int", .linkage = .Strong }); }
fn powInt(base: i64, exp: i64) callconv(.C) i64 {
return math.pow(i64, base, exp); return math.pow(i64, base, exp);
} }
// Str.split // Str.split
const RocStr = struct { const RocStr = struct {
strBytesPtrs: [*]u8, str_bytes_ptrs: [*]u8,
strLen: usize, str_len: usize,
pub fn init(bytes: [*]u8, len: usize) RocStr { pub fn init(bytes: [*]u8, len: usize) RocStr {
return RocStr { return RocStr {
.strBytesPtrs = bytes, .str_bytes_ptrs = bytes,
.strLen = len .str_len = len
}; };
} }
pub fn eq(self: RocStr, other: RocStr) bool { pub fn eq(self: RocStr, other: RocStr) bool {
if (self.strLen != other.strLen) { if (self.str_len != other.str_len) {
return false; return false;
} }
var areEq: bool = true; var areEq: bool = true;
var index: usize = 0; var index: usize = 0;
while (index < self.strLen and areEq) { while (index < self.str_len and areEq) {
areEq = areEq and self.strBytesPtrs[index] == other.strBytesPtrs[index]; areEq = areEq and self.str_bytes_ptrs[index] == other.str_bytes_ptrs[index];
index = index + 1; index = index + 1;
} }
@ -43,184 +51,185 @@ const RocStr = struct {
} }
test "RocStr.eq: equal" { test "RocStr.eq: equal" {
const str1Len = 3; const str1_len = 3;
var str1: [str1Len]u8 = "abc".*; var str1: [str1_len]u8 = "abc".*;
const str1Ptr: [*]u8 = &str1; const str1_ptr: [*]u8 = &str1;
var rocStr1 = RocStr.init(str1Ptr, str1Len); var roc_str1 = RocStr.init(str1_ptr, str1_len);
const str2Len = 3; const str2_len = 3;
var str2: [str2Len]u8 = "abc".*; var str2: [str2_len]u8 = "abc".*;
const str2Ptr: [*]u8 = &str2; const str2_ptr: [*]u8 = &str2;
var rocStr2 = RocStr.init(str2Ptr, str2Len); var roc_str2 = RocStr.init(str2_ptr, str2_len);
expect(RocStr.eq(rocStr1, rocStr2)); expect(RocStr.eq(roc_str1, roc_str2));
} }
test "RocStr.eq: not equal different length" { test "RocStr.eq: not equal different length" {
const str1Len = 4; const str1_len = 4;
var str1: [str1Len]u8 = "abcd".*; var str1: [str1_len]u8 = "abcd".*;
const str1Ptr: [*]u8 = &str1; const str1_ptr: [*]u8 = &str1;
var rocStr1 = RocStr.init(str1Ptr, str1Len); var roc_str1 = RocStr.init(str1_ptr, str1_len);
const str2Len = 3; const str2_len = 3;
var str2: [str2Len]u8 = "abc".*; var str2: [str2_len]u8 = "abc".*;
const str2Ptr: [*]u8 = &str2; const str2_ptr: [*]u8 = &str2;
var rocStr2 = RocStr.init(str2Ptr, str2Len); var roc_str2 = RocStr.init(str2_ptr, str2_len);
expect(!RocStr.eq(rocStr1, rocStr2)); expect(!RocStr.eq(roc_str1, roc_str2));
} }
test "RocStr.eq: not equal same length" { test "RocStr.eq: not equal same length" {
const str1Len = 3; const str1_len = 3;
var str1: [str1Len]u8 = "acb".*; var str1: [str1_len]u8 = "acb".*;
const str1Ptr: [*]u8 = &str1; const str1_ptr: [*]u8 = &str1;
var rocStr1 = RocStr.init(str1Ptr, str1Len); var roc_str1 = RocStr.init(str1_ptr, str1_len);
const str2Len = 3; const str2_len = 3;
var str2: [str2Len]u8 = "abc".*; var str2: [str2_len]u8 = "abc".*;
const str2Ptr: [*]u8 = &str2; const str2_ptr: [*]u8 = &str2;
var rocStr2 = RocStr.init(str2Ptr, str2Len); var roc_str2 = RocStr.init(str2_ptr, str2_len);
expect(!RocStr.eq(rocStr1, rocStr2)); expect(!RocStr.eq(roc_str1, roc_str2));
} }
}; };
export fn str_split_in_place_( comptime { @export(strSplitInPlace, .{ .name = str_namespace ++ ".str_split_in_place", .linkage = .Strong }); }
fn strSplitInPlace(
array: [*]RocStr, array: [*]RocStr,
arrayLen: usize, array_len: usize,
strBytesPtrs: [*]u8, str_bytes_ptrs: [*]u8,
strLen: usize, str_len: usize,
delimiterBytes: [*]u8, delimiter_bytes: [*]u8,
delimiterLen: usize delimiter_len: usize
) void { ) callconv(.C) void {
var retArrayIndex : usize = 0; var ret_array_index : usize = 0;
var sliceStartIndex : usize = 0; var sliceStart_index : usize = 0;
var strIndex : usize = 0; var str_index : usize = 0;
if (strLen > delimiterLen) { if (str_len > delimiter_len) {
const endIndex : usize = strLen - delimiterLen; const end_index : usize = str_len - delimiter_len;
while (strIndex <= endIndex) { while (str_index <= end_index) {
var delimiterIndex : usize = 0; var delimiter_index : usize = 0;
var matchesDelimiter = true; var matches_delimiter = true;
while (delimiterIndex < delimiterLen) { while (delimiter_index < delimiter_len) {
var delimiterChar = delimiterBytes[delimiterIndex]; var delimiterChar = delimiter_bytes[delimiter_index];
var strChar = strBytesPtrs[strIndex + delimiterIndex]; var strChar = str_bytes_ptrs[str_index + delimiter_index];
if (delimiterChar != strChar) { if (delimiterChar != strChar) {
matchesDelimiter = false; matches_delimiter = false;
break; break;
} }
delimiterIndex += 1; delimiter_index += 1;
} }
if (matchesDelimiter) { if (matches_delimiter) {
array[retArrayIndex] = RocStr.init(strBytesPtrs + sliceStartIndex, strIndex - sliceStartIndex); array[ret_array_index] = RocStr.init(str_bytes_ptrs + sliceStart_index, str_index - sliceStart_index);
sliceStartIndex = strIndex + delimiterLen; sliceStart_index = str_index + delimiter_len;
retArrayIndex += 1; ret_array_index += 1;
strIndex += delimiterLen; str_index += delimiter_len;
} else { } else {
strIndex += 1; str_index += 1;
} }
} }
} }
array[retArrayIndex] = RocStr.init(strBytesPtrs + sliceStartIndex, strLen - sliceStartIndex); array[ret_array_index] = RocStr.init(str_bytes_ptrs + sliceStart_index, str_len - sliceStart_index);
} }
test "str_split_in_place_: no delimiter" { test "strSplitInPlace: no delimiter" {
// Str.split "abc" "!" == [ "abc" ] // Str.split "abc" "!" == [ "abc" ]
var str: [3]u8 = "abc".*; var str: [3]u8 = "abc".*;
const strPtr: [*]u8 = &str; const str_ptr: [*]u8 = &str;
var delimiter: [1]u8 = "!".*; var delimiter: [1]u8 = "!".*;
const delimiterPtr: [*]u8 = &delimiter; const delimiter_ptr: [*]u8 = &delimiter;
var array: [1]RocStr = undefined; var array: [1]RocStr = undefined;
const arrayPtr: [*]RocStr = &array; const array_ptr: [*]RocStr = &array;
str_split_in_place_( strSplitInPlace(
arrayPtr, array_ptr,
1, 1,
strPtr, str_ptr,
3, 3,
delimiterPtr, delimiter_ptr,
1 1
); );
var expected = [1]RocStr{ var expected = [1]RocStr{
RocStr.init(strPtr, 3), RocStr.init(str_ptr, 3),
}; };
expect(array.len == expected.len); expect(array.len == expected.len);
expect(RocStr.eq(array[0], expected[0])); expect(RocStr.eq(array[0], expected[0]));
} }
test "str_split_in_place_: delimiter on sides" { test "strSplitInPlace: delimiter on sides" {
// Str.split "tttghittt" "ttt" == [ "", "ghi", "" ] // Str.split "tttghittt" "ttt" == [ "", "ghi", "" ]
const strLen: usize = 9; const str_len: usize = 9;
var str: [strLen]u8 = "tttghittt".*; var str: [str_len]u8 = "tttghittt".*;
const strPtr: [*]u8 = &str; const str_ptr: [*]u8 = &str;
const delimiterLen = 3; const delimiter_len = 3;
var delimiter: [delimiterLen]u8 = "ttt".*; var delimiter: [delimiter_len]u8 = "ttt".*;
const delimiterPtr: [*]u8 = &delimiter; const delimiter_ptr: [*]u8 = &delimiter;
const arrayLen : usize = 3; const array_len : usize = 3;
var array: [arrayLen]RocStr = [_]RocStr{ var array: [array_len]RocStr = [_]RocStr{
undefined , undefined ,
undefined, undefined,
undefined, undefined,
}; };
const arrayPtr: [*]RocStr = &array; const array_ptr: [*]RocStr = &array;
str_split_in_place_( strSplitInPlace(
arrayPtr, array_ptr,
arrayLen, array_len,
strPtr, str_ptr,
strLen, str_len,
delimiterPtr, delimiter_ptr,
delimiterLen delimiter_len
); );
const expectedStrLen: usize = 3; const expected_str_len: usize = 3;
var expectedStr: [expectedStrLen]u8 = "ghi".*; var expected_str: [expected_str_len]u8 = "ghi".*;
const expectedStrPtr: [*]u8 = &expectedStr; const expected_str_ptr: [*]u8 = &expected_str;
var expectedRocStr = RocStr.init(expectedStrPtr, expectedStrLen); var expectedRocStr = RocStr.init(expected_str_ptr, expected_str_len);
expect(array.len == 3); expect(array.len == 3);
expect(array[0].strLen == 0); expect(array[0].str_len == 0);
expect(RocStr.eq(array[1], expectedRocStr)); expect(RocStr.eq(array[1], expectedRocStr));
expect(array[2].strLen == 0); expect(array[2].str_len == 0);
} }
test "str_split_in_place_: three pieces" { test "strSplitInPlace: three pieces" {
// Str.split "a!b!c" "!" == [ "a", "b", "c" ] // Str.split "a!b!c" "!" == [ "a", "b", "c" ]
const strLen: usize = 5; const str_len: usize = 5;
var str: [strLen]u8 = "a!b!c".*; var str: [str_len]u8 = "a!b!c".*;
const strPtr: [*]u8 = &str; const str_ptr: [*]u8 = &str;
const delimiterLen = 1; const delimiter_len = 1;
var delimiter: [delimiterLen]u8 = "!".*; var delimiter: [delimiter_len]u8 = "!".*;
const delimiterPtr: [*]u8 = &delimiter; const delimiter_ptr: [*]u8 = &delimiter;
const arrayLen : usize = 3; const array_len : usize = 3;
var array: [arrayLen]RocStr = undefined; var array: [array_len]RocStr = undefined;
const arrayPtr: [*]RocStr = &array; const array_ptr: [*]RocStr = &array;
str_split_in_place_( strSplitInPlace(
arrayPtr, array_ptr,
arrayLen, array_len,
strPtr, str_ptr,
strLen, str_len,
delimiterPtr, delimiter_ptr,
delimiterLen delimiter_len
); );
var a: [1]u8 = "a".*; var a: [1]u8 = "a".*;
@ -232,133 +241,134 @@ test "str_split_in_place_: three pieces" {
var c: [1]u8 = "c".*; var c: [1]u8 = "c".*;
const c_ptr: [*]u8 = &c; const c_ptr: [*]u8 = &c;
var expectedArray = [arrayLen]RocStr{ var expected_array = [array_len]RocStr{
RocStr{ RocStr{
.strBytesPtrs = a_ptr, .str_bytes_ptrs = a_ptr,
.strLen = 1, .str_len = 1,
}, },
RocStr{ RocStr{
.strBytesPtrs = b_ptr, .str_bytes_ptrs = b_ptr,
.strLen = 1, .str_len = 1,
}, },
RocStr{ RocStr{
.strBytesPtrs = c_ptr, .str_bytes_ptrs = c_ptr,
.strLen = 1, .str_len = 1,
} }
}; };
expect(expectedArray.len == array.len); expect(expected_array.len == array.len);
expect(RocStr.eq(array[0], expectedArray[0])); expect(RocStr.eq(array[0], expected_array[0]));
expect(RocStr.eq(array[1], expectedArray[1])); expect(RocStr.eq(array[1], expected_array[1]));
expect(RocStr.eq(array[2], expectedArray[2])); expect(RocStr.eq(array[2], expected_array[2]));
} }
// This is used for `Str.split : Str, Str -> array Str // This is used for `Str.split : Str, Str -> Array Str
// It is used to count how many segments the input `Str` // It is used to count how many segments the input `_str`
// needs to be broken into, so that we can allocate a array // needs to be broken into, so that we can allocate a array
// of that size. It always returns at least 1. // of that size. It always returns at least 1.
export fn count_segments_( comptime { @export(countSegments, .{ .name = str_namespace ++ ".count_segements", .linkage = .Strong }); }
strBytesPtrs: [*]u8, fn countSegments(
strLen: usize, str_bytes_ptrs: [*]u8,
delimiterBytes: [*]u8, str_len: usize,
delimiterLen: usize delimiter_bytes: [*]u8,
) i64 { delimiter_len: usize
) callconv(.C) i64 {
var count: i64 = 1; var count: i64 = 1;
if (strLen > delimiterLen) { if (str_len > delimiter_len) {
var strIndex: usize = 0; var str_index: usize = 0;
const endCond: usize = strLen - delimiterLen; const end_cond: usize = str_len - delimiter_len;
while (strIndex < endCond) { while (str_index < end_cond) {
var delimiterIndex: usize = 0; var delimiter_index: usize = 0;
var matchesDelimiter = true; var matches_delimiter = true;
while (delimiterIndex < delimiterLen) { while (delimiter_index < delimiter_len) {
const delimiterChar = delimiterBytes[delimiterIndex]; const delimiterChar = delimiter_bytes[delimiter_index];
const strChar = strBytesPtrs[strIndex + delimiterIndex]; const strChar = str_bytes_ptrs[str_index + delimiter_index];
if (delimiterChar != strChar) { if (delimiterChar != strChar) {
matchesDelimiter = false; matches_delimiter = false;
break; break;
} }
delimiterIndex += 1; delimiter_index += 1;
} }
if (matchesDelimiter) { if (matches_delimiter) {
count += 1; count += 1;
} }
strIndex += 1; str_index += 1;
} }
} }
return count; return count;
} }
test "count_segments_: long delimiter" { test "countSegments: long delimiter" {
// Str.split "str" "delimiter" == [ "str" ] // Str.split "str" "delimiter" == [ "str" ]
// 1 segment // 1 segment
const strLen: usize = 3; const str_len: usize = 3;
var str: [strLen]u8 = "str".*; var str: [str_len]u8 = "str".*;
const strPtr: [*]u8 = &str; const str_ptr: [*]u8 = &str;
const delimiterLen = 9; const delimiter_len = 9;
var delimiter: [delimiterLen]u8 = "delimiter".*; var delimiter: [delimiter_len]u8 = "delimiter".*;
const delimiterPtr: [*]u8 = &delimiter; const delimiter_ptr: [*]u8 = &delimiter;
const segmentsCount = count_segments_( const segments_count = countSegments(
strPtr, str_ptr,
strLen, str_len,
delimiterPtr, delimiter_ptr,
delimiterLen delimiter_len
); );
expect(segmentsCount == 1); expect(segments_count == 1);
} }
test "count_segments_: delimiter at start" { test "countSegments: delimiter at start" {
// Str.split "hello there" "hello" == [ "", " there" ] // Str.split "hello there" "hello" == [ "", " there" ]
// 2 segments // 2 segments
const strLen: usize = 11; const str_len: usize = 11;
var str: [strLen]u8 = "hello there".*; var str: [str_len]u8 = "hello there".*;
const strPtr: [*]u8 = &str; const str_ptr: [*]u8 = &str;
const delimiterLen = 5; const delimiter_len = 5;
var delimiter: [delimiterLen]u8 = "hello".*; var delimiter: [delimiter_len]u8 = "hello".*;
const delimiterPtr: [*]u8 = &delimiter; const delimiter_ptr: [*]u8 = &delimiter;
const segmentsCount = count_segments_( const segments_count = countSegments(
strPtr, str_ptr,
strLen, str_len,
delimiterPtr, delimiter_ptr,
delimiterLen delimiter_len
); );
expect(segmentsCount == 2); expect(segments_count == 2);
} }
test "count_segments_: delimiter interspered" { test "countSegments: delimiter interspered" {
// Str.split "a!b!c" "!" == [ "a", "b", "c" ] // Str.split "a!b!c" "!" == [ "a", "b", "c" ]
// 3 segments // 3 segments
const strLen: usize = 5; const str_len: usize = 5;
var str: [strLen]u8 = "a!b!c".*; var str: [str_len]u8 = "a!b!c".*;
const strPtr: [*]u8 = &str; const str_ptr: [*]u8 = &str;
const delimiterLen = 1; const delimiter_len = 1;
var delimiter: [delimiterLen]u8 = "!".*; var delimiter: [delimiter_len]u8 = "!".*;
const delimiterPtr: [*]u8 = &delimiter; const delimiter_ptr: [*]u8 = &delimiter;
const segmentsCount = count_segments_( const segments_count = countSegments(
strPtr, str_ptr,
strLen, str_len,
delimiterPtr, delimiter_ptr,
delimiterLen delimiter_len
); );
expect(segmentsCount == 3); expect(segments_count == 3);
} }

View file

@ -16,3 +16,10 @@ pub fn get_bytes() -> Vec<u8> {
.expect("Unable to read builtins bitcode"); .expect("Unable to read builtins bitcode");
buffer buffer
} }
pub const MATH_ATAN: &str = "roc_builtins.math.atan";
pub const MATH_IS_FINITE: &str = "roc_builtins.math.is_finite";
pub const MATH_POW_INT: &str = "roc_builtins.math.pow_int";
pub const STR_COUNT_SEGEMENTS: &str = "roc_builtins.str.count_segements";
pub const STR_STR_SPLIT_IN_PLACE: &str = "roc_builtins.str.str_split_in_place";

View file

@ -2530,7 +2530,12 @@ fn build_int_binop<'a, 'ctx, 'env>(
NumLte => bd.build_int_compare(SLE, lhs, rhs, "int_lte").into(), NumLte => bd.build_int_compare(SLE, lhs, rhs, "int_lte").into(),
NumRemUnchecked => bd.build_int_signed_rem(lhs, rhs, "rem_int").into(), NumRemUnchecked => bd.build_int_signed_rem(lhs, rhs, "rem_int").into(),
NumDivUnchecked => bd.build_int_signed_div(lhs, rhs, "div_int").into(), NumDivUnchecked => bd.build_int_signed_div(lhs, rhs, "div_int").into(),
NumPowInt => call_bitcode_fn(NumPowInt, env, &[lhs.into(), rhs.into()], "pow_int_"), NumPowInt => call_bitcode_fn(
NumPowInt,
env,
&[lhs.into(), rhs.into()],
&bitcode::MATH_POW_INT,
),
_ => { _ => {
unreachable!("Unrecognized int binary operation: {:?}", op); unreachable!("Unrecognized int binary operation: {:?}", op);
} }
@ -2578,7 +2583,8 @@ fn build_float_binop<'a, 'ctx, 'env>(
let result = bd.build_float_add(lhs, rhs, "add_float"); let result = bd.build_float_add(lhs, rhs, "add_float");
let is_finite = let is_finite =
call_bitcode_fn(NumIsFinite, env, &[result.into()], "is_finite_").into_int_value(); call_bitcode_fn(NumIsFinite, env, &[result.into()], &bitcode::MATH_IS_FINITE)
.into_int_value();
let then_block = context.append_basic_block(parent, "then_block"); let then_block = context.append_basic_block(parent, "then_block");
let throw_block = context.append_basic_block(parent, "throw_block"); let throw_block = context.append_basic_block(parent, "throw_block");
@ -2599,7 +2605,8 @@ fn build_float_binop<'a, 'ctx, 'env>(
let result = bd.build_float_add(lhs, rhs, "add_float"); let result = bd.build_float_add(lhs, rhs, "add_float");
let is_finite = let is_finite =
call_bitcode_fn(NumIsFinite, env, &[result.into()], "is_finite_").into_int_value(); call_bitcode_fn(NumIsFinite, env, &[result.into()], &bitcode::MATH_IS_FINITE)
.into_int_value();
let is_infinite = bd.build_not(is_finite, "negate"); let is_infinite = bd.build_not(is_finite, "negate");
let struct_type = context.struct_type( let struct_type = context.struct_type(
@ -2728,8 +2735,8 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
env.context.i64_type(), env.context.i64_type(),
"num_floor", "num_floor",
), ),
NumIsFinite => call_bitcode_fn(NumIsFinite, env, &[arg.into()], "is_finite_"), NumIsFinite => call_bitcode_fn(NumIsFinite, env, &[arg.into()], &bitcode::MATH_IS_FINITE),
NumAtan => call_bitcode_fn(NumAtan, env, &[arg.into()], "atan_"), NumAtan => call_bitcode_fn(NumAtan, env, &[arg.into()], &bitcode::MATH_ATAN),
_ => { _ => {
unreachable!("Unrecognized int unary operation: {:?}", op); unreachable!("Unrecognized int unary operation: {:?}", op);
} }