Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ class CSharpBackendTest {
|static TestGlobal()
|{
| builder__0 = new C::OrderedDictionary<string, string>();
| Map1 = C::Mapped.ToMap(builder__0);
| Map1 = C::Mapped.ToMap(C::Mapped.AsReadOnly(builder__0));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure whether this extra cast here a problem?

| mapped__0 = C::Mapped.AsReadOnly(builder__0);
| Map2 = C::Mapped.ToMap(mapped__0);
|}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1897,12 +1897,13 @@ class JsBackendTest {
| export function maybeLength(a_0) {
| let return_0;
| let t_3;
| let t_4;
| if (a_0 == null) {
| return_0 = null;
| } else {
| const a_1 = a_0;
| t_3 = a_1.length;
| return_0 = stringCountBetween_0(a_1, 0, t_3);
| t_4 = a_0;
| t_3 = t_4.length;
| return_0 = stringCountBetween_0(t_4, 0, t_3);
| }
| return return_0;
| };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ import lang.temper.name.OutName
import lang.temper.name.ParsedName
import lang.temper.name.name
import lang.temper.type.WellKnownTypes
import lang.temper.type2.DefinedNonNullType
import lang.temper.type2.DefinedType
import lang.temper.type2.MkType2
import lang.temper.type2.Signature2
import lang.temper.type2.Type2
import lang.temper.type2.withType
Expand Down Expand Up @@ -678,19 +676,8 @@ private object CmpGeneric : MethodCall(
returnType: Type2,
translator: RustTranslator,
): Rust.Expr {
// Work around core.type StringIndexOption.compareTo() typing if needed.
val self = arguments.getOrNull(0)
val effectiveArgs = when ((self?.type as? DefinedNonNullType)?.definition) {
WellKnownTypes.stringIndexTypeDefinition -> buildList {
// Left should be an option, not a string index, but we don't get the function type that way.
val optionType = MkType2(WellKnownTypes.stringIndexOptionTypeDefinition).get()
add(TypedArg((self.expr as Rust.Expr).wrapSome(), optionType))
addAll(arguments.subListToEnd(1))
}
else -> arguments
}
// And cast result as i32 for be-rust int expectations.
return super.inlineToTree(pos, effectiveArgs, returnType, translator).infix(RustOperator.As, "i32".toId(pos))
// Cast result as i32 for temper Int type expectations.
return super.inlineToTree(pos, arguments, returnType, translator).infix(RustOperator.As, "i32".toId(pos))
}
}

Expand Down
128 changes: 117 additions & 11 deletions be-rust/src/commonTest/kotlin/lang/temper/be/rust/RustBackendTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -96,28 +96,25 @@ class RustBackendTest {
| pub (crate) fn init() -> temper_core::Result<()> {
| static INIT_ONCE: std::sync::OnceLock<temper_core::Result<()>> = std::sync::OnceLock::new();
| INIT_ONCE.get_or_init(| |{
| let stringifyValue__0: std::sync::Arc<dyn Fn (i32) -> std::sync::Arc<String> + std::marker::Send + std::marker::Sync> = std::sync::Arc::new(crate::bar::stringify.clone());
| println!("{}", "Foo");
| STRINGIFY_VALUE_HERE.set(std::sync::Arc::new(stringifyHere__0.clone())).unwrap_or_else(| _ | panic!());
| let stringifyValueHere__0: std::sync::Arc<dyn Fn (i32) -> std::sync::Arc<String> + std::marker::Send + std::marker::Sync> = std::sync::Arc::new(stringifyHere__0.clone());
| Ok(())
| }).clone()
| }
| static STRINGIFY_VALUE_HERE: std::sync::OnceLock<std::sync::Arc<dyn Fn (i32) -> std::sync::Arc<String> + std::marker::Send + std::marker::Sync>> = std::sync::OnceLock::new();
| fn stringify_value_here() -> std::sync::Arc<dyn Fn (i32) -> std::sync::Arc<String> + std::marker::Send + std::marker::Sync> {
| ( * STRINGIFY_VALUE_HERE.get().unwrap()).clone()
| }
| fn stringifyHere__0(i__0: i32) -> std::sync::Arc<String> {
| return temper_core::int_to_string(i__0, None);
| }
| pub fn hi(nums__0: impl temper_core::ToListed<i32>) -> std::sync::Arc<String> {
| let nums__0 = nums__0.to_listed();
| let a__0: std::sync::Arc<String> = temper_core::listed::join( & ( * nums__0), std::sync::Arc::new("".to_string()), & crate::bar::stringify.clone());
| let b__0: std::sync::Arc<String> = temper_core::listed::join( & ( * nums__0), std::sync::Arc::new("".to_string()), & ( * crate::bar::stringify_value().clone()));
| let b__0: std::sync::Arc<String> = temper_core::listed::join( & ( * nums__0), std::sync::Arc::new("".to_string()), & crate::bar::stringify.clone());
| let c__0: std::sync::Arc<String> = temper_core::listed::join( & ( * nums__0), std::sync::Arc::new("".to_string()), & stringifyHere__0.clone());
| let d__0: std::sync::Arc<String> = temper_core::listed::join( & ( * nums__0), std::sync::Arc::new("".to_string()), & ( * stringify_value_here().clone()));
| let d__0: std::sync::Arc<String> = temper_core::listed::join( & ( * nums__0), std::sync::Arc::new("".to_string()), & stringifyHere__0.clone());
| return std::sync::Arc::new(format!("{}{}{}{}", a__0, b__0.clone(), c__0.clone(), d__0.clone()));
| }
| pub fn make_talk_here(talker__1: crate::bar::Talker) {
| talker__1.talk();
| pub fn make_talk_here(talker__0: crate::bar::Talker) {
| talker__0.talk();
| }
|
| ```
Expand Down Expand Up @@ -173,8 +170,8 @@ class RustBackendTest {
| pub fn stringify(i__1: i32) -> std::sync::Arc<String> {
| return temper_core::int_to_string(i__1, None);
| }
| pub fn make_talk(talker__0: Talker) {
| talker__0.talk();
| pub fn make_talk(talker__1: Talker) {
| talker__1.talk();
| }
|
| ```
Expand Down Expand Up @@ -2768,6 +2765,115 @@ class RustBackendTest {
""".trimMargin(),
)
}

@Test
fun decodeHexTest() = assertGenerateWanted(
temper = """
|let decodeHexUnsigned(
| sourceText: String, start: StringIndex, limit: StringIndex
|): Int {
| var n = 0;
| var i = start;
| while (i.compareTo(limit) < 0) {
| let cp = sourceText[i];
| let digit = if (char'0' <= cp && cp <= char'0') {
| cp - char'0'
| } else if (char'A' <= cp && cp <= char'F') {
| cp - char'A' + 10
| } else if (char'a' <= cp && cp <= char'f') {
| cp - char'a' + 10
| } else {
| return -1;
| }
| n = (n * 16) + digit;
| i = sourceText.next(i);
| }
| n
|}
""".trimMargin(),
rust = """
|pub (crate) fn init() -> temper_core::Result<()> {
| static INIT_ONCE: std::sync::OnceLock<temper_core::Result<()>> = std::sync::OnceLock::new();
| INIT_ONCE.get_or_init(| |{
| Ok(())
| }).clone()
|}
|fn decodeHexUnsigned__0(sourceText__0: impl temper_core::ToArcString, start__0: usize, limit__0: usize) -> i32 {
| let sourceText__0 = sourceText__0.to_arc_string();
| let return__0: i32;
| let mut t___0: usize;
| let mut t___1: bool;
| let mut t___2: bool;
| let mut t___3: bool;
| let mut t___4: i32;
| 'fn__0: {
| let mut n__0: i32 = 0;
| let mut i__0: usize = start__0;
| 'loop___0: loop {
| if ! (Some(Some(i__0).cmp( & Some(limit__0)) as i32) < Some(0)) {
| break;
| }
| let cp__0: i32 = temper_core::string::get( & sourceText__0, i__0);
| if Some(48) <= Some(cp__0) {
| t___1 = Some(cp__0) <= Some(48);
| } else {
| t___1 = false;
| }
| if t___1 {
| t___4 = cp__0.wrapping_sub(48);
| } else {
| if Some(65) <= Some(cp__0) {
| t___2 = Some(cp__0) <= Some(70);
| } else {
| t___2 = false;
| }
| if t___2 {
| t___4 = cp__0.wrapping_sub(65).wrapping_add(10);
| } else {
| if Some(97) <= Some(cp__0) {
| t___3 = Some(cp__0) <= Some(102);
| } else {
| t___3 = false;
| }
| if t___3 {
| t___4 = cp__0.wrapping_sub(97).wrapping_add(10);
| } else {
| return__0 = -1;
| break 'fn__0;
| }
| }
| }
| let digit__0: i32 = t___4;
| n__0 = n__0.wrapping_mul(16).wrapping_add(digit__0);
| t___0 = temper_core::string::next( & sourceText__0, i__0);
| i__0 = t___0;
| }
| return__0 = n__0;
| }
| return return__0;
|}
""".trimMargin(),
)

@Test
fun stringIndexOptionCompareToStringIndexMinimal() = assertGenerateWanted(
temper = """
|export let notEmpty(start: StringIndex, limit: StringIndex): Boolean {
| start.compareTo(limit) < 0
|}
""".trimMargin(),
rust = """
|pub (crate) fn init() -> temper_core::Result<()> {
| static INIT_ONCE: std::sync::OnceLock<temper_core::Result<()>> = std::sync::OnceLock::new();
| INIT_ONCE.get_or_init(| |{
| Ok(())
| }).clone()
|}
|pub fn not_empty(start__0: usize, limit__0: usize) -> bool {
| return Some(Some(start__0).cmp( & Some(limit__0)) as i32) < Some(0);
|}
""".trimMargin(),
)
}

private fun assertGenerateWanted(
Expand Down
13 changes: 0 additions & 13 deletions be/src/commonMain/kotlin/lang/temper/be/tmpl/TmpLTranslator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ import lang.temper.name.SourceName
import lang.temper.name.Symbol
import lang.temper.name.TemperName
import lang.temper.name.Temporary
import lang.temper.type.BindMemberAccessor
import lang.temper.type.DotHelper
import lang.temper.type.MethodKind
import lang.temper.type.MethodShape
Expand Down Expand Up @@ -1753,15 +1752,6 @@ class TmpLTranslator internal constructor(
translateDotHelperCall(
tree,
callee = effectiveCallee,
outerCallTree = null,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no outer call tree.

typeActuals = typeActuals,
)
} else if (dotHelperFromCallOrNull(effectiveCallee)?.memberAccessor is BindMemberAccessor) {
check(effectiveCallee is CallTree)
translateDotHelperCall(
effectiveCallee,
callee = effectiveCallee.child(0),
outerCallTree = tree,
typeActuals = typeActuals,
)
} else {
Expand Down Expand Up @@ -2771,20 +2761,17 @@ class TmpLTranslator internal constructor(
translateDotHelperCall(
callTree,
callTree.child(0),
null,
emptyList(),
)

private fun translateDotHelperCall(
callTree: CallTree,
callee: Tree,
outerCallTree: CallTree?,
typeActuals: List<Tree>,
): StmtOrExpr {
val dotTranslation = TranslateDotHelper.translate(
callTree = callTree,
callee = callee,
outerCallTree = outerCallTree,
typeActuals = typeActuals,
translator = this,
)
Expand Down
Loading
Loading