mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
Add SwiftUI demo
This commit is contained in:
parent
6e19ca1da6
commit
f7b2a73a75
7 changed files with 130 additions and 3 deletions
|
@ -297,7 +297,7 @@ mod cli_run {
|
||||||
let file_name = example_file(dir_name, example.filename);
|
let file_name = example_file(dir_name, example.filename);
|
||||||
|
|
||||||
match example.executable_filename {
|
match example.executable_filename {
|
||||||
"form" | "hello-gui" | "breakout" | "ruby" => {
|
"form" | "hello-gui" | "breakout" | "ruby" | "swiftui" => {
|
||||||
// Since these require things the build system often doesn't have
|
// Since these require things the build system often doesn't have
|
||||||
// (e.g. GUIs open a window, Ruby needs ruby installed, WASM needs a browser)
|
// (e.g. GUIs open a window, Ruby needs ruby installed, WASM needs a browser)
|
||||||
// we do `roc build` on them but don't run them.
|
// we do `roc build` on them but don't run them.
|
||||||
|
@ -548,6 +548,14 @@ mod cli_run {
|
||||||
use_valgrind: false,
|
use_valgrind: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
swiftui:"swiftui" => Example {
|
||||||
|
filename: "main.roc",
|
||||||
|
executable_filename: "swiftui",
|
||||||
|
stdin: &[],
|
||||||
|
input_file: None,
|
||||||
|
expected_ending: "",
|
||||||
|
use_valgrind: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! benchmarks {
|
macro_rules! benchmarks {
|
||||||
|
|
|
@ -423,6 +423,7 @@ pub fn build_c_host_native(
|
||||||
command.output().unwrap()
|
command.output().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn build_swift_host_native(
|
pub fn build_swift_host_native(
|
||||||
env_path: &str,
|
env_path: &str,
|
||||||
env_home: &str,
|
env_home: &str,
|
||||||
|
@ -431,16 +432,25 @@ pub fn build_swift_host_native(
|
||||||
opt_level: OptLevel,
|
opt_level: OptLevel,
|
||||||
shared_lib_path: Option<&Path>,
|
shared_lib_path: Option<&Path>,
|
||||||
objc_header_path: Option<&str>,
|
objc_header_path: Option<&str>,
|
||||||
|
arch: Architecture,
|
||||||
) -> Output {
|
) -> Output {
|
||||||
if shared_lib_path.is_some() {
|
if shared_lib_path.is_some() {
|
||||||
unimplemented!("Linking a shared library to Swift not yet implemented");
|
unimplemented!("Linking a shared library to Swift not yet implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut command = Command::new("xcrun"); // xcrun helps swiftc to find the right header files
|
let mut command = Command::new("arch");
|
||||||
command
|
command
|
||||||
.env_clear()
|
.env_clear()
|
||||||
.env("PATH", &env_path)
|
.env("PATH", &env_path)
|
||||||
.env("HOME", &env_home)
|
.env("HOME", &env_home);
|
||||||
|
|
||||||
|
match arch {
|
||||||
|
Architecture::Aarch64(_) => command.arg("-arm64"),
|
||||||
|
_ => command.arg(format!("-{}", arch)),
|
||||||
|
};
|
||||||
|
|
||||||
|
command
|
||||||
|
.arg("xcrun") // xcrun helps swiftc to find the right header files
|
||||||
.arg("swiftc")
|
.arg("swiftc")
|
||||||
.args(sources)
|
.args(sources)
|
||||||
.arg("-emit-object")
|
.arg("-emit-object")
|
||||||
|
@ -734,6 +744,7 @@ pub fn rebuild_host(
|
||||||
swift_host_header_src
|
swift_host_header_src
|
||||||
.exists()
|
.exists()
|
||||||
.then(|| swift_host_header_src.to_str().unwrap()),
|
.then(|| swift_host_header_src.to_str().unwrap()),
|
||||||
|
target.architecture,
|
||||||
);
|
);
|
||||||
validate_output("host.swift", "swiftc", output);
|
validate_output("host.swift", "swiftc", output);
|
||||||
}
|
}
|
||||||
|
|
6
examples/swiftui/main.roc
Normal file
6
examples/swiftui/main.roc
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
app "swiftui"
|
||||||
|
packages { pf: "platform/main.roc" }
|
||||||
|
imports []
|
||||||
|
provides [main] to pf
|
||||||
|
|
||||||
|
main = "Roc <3 Swift!\n"
|
9
examples/swiftui/platform/host.h
Normal file
9
examples/swiftui/platform/host.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
struct RocStr {
|
||||||
|
char* bytes;
|
||||||
|
size_t len;
|
||||||
|
size_t capacity;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void roc__mainForHost_1_exposed_generic(const struct RocStr *data);
|
78
examples/swiftui/platform/host.swift
Normal file
78
examples/swiftui/platform/host.swift
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
@_cdecl("roc_alloc")
|
||||||
|
func rocAlloc(size: Int, _alignment: UInt) -> UInt {
|
||||||
|
guard let ptr = malloc(size) else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return UInt(bitPattern: ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
@_cdecl("roc_dealloc")
|
||||||
|
func rocDealloc(ptr: UInt, _alignment: UInt) {
|
||||||
|
free(UnsafeMutableRawPointer(bitPattern: ptr))
|
||||||
|
}
|
||||||
|
|
||||||
|
@_cdecl("roc_realloc")
|
||||||
|
func rocRealloc(ptr: UInt, _oldSize: Int, newSize: Int, _alignment: UInt) -> UInt {
|
||||||
|
guard let ptr = realloc(UnsafeMutableRawPointer(bitPattern: ptr), newSize) else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return UInt(bitPattern: ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isSmallString(rocStr: RocStr) -> Bool {
|
||||||
|
return rocStr.capacity < 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStrLen(rocStr: RocStr) -> Int {
|
||||||
|
if isSmallString(rocStr: rocStr) {
|
||||||
|
// Small String length is last in the byte of capacity.
|
||||||
|
var cap = rocStr.capacity
|
||||||
|
let count = MemoryLayout.size(ofValue: cap)
|
||||||
|
let bytes = Data(bytes: &cap, count: count)
|
||||||
|
let lastByte = bytes[count - 1]
|
||||||
|
return Int(lastByte ^ 0b1000_0000)
|
||||||
|
} else {
|
||||||
|
return rocStr.len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSwiftString(rocStr: RocStr) -> String {
|
||||||
|
let length = getStrLen(rocStr: rocStr)
|
||||||
|
|
||||||
|
if isSmallString(rocStr: rocStr) {
|
||||||
|
let data: Data = withUnsafePointer(to: rocStr) { ptr in
|
||||||
|
Data(bytes: ptr, count: length)
|
||||||
|
}
|
||||||
|
return String(data: data, encoding: .utf8)!
|
||||||
|
} else {
|
||||||
|
let data = Data(bytes: rocStr.bytes, count: length)
|
||||||
|
return String(data: data, encoding: .utf8)!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ContentView: View {
|
||||||
|
var str: String
|
||||||
|
|
||||||
|
init() {
|
||||||
|
var rocStr = RocStr()
|
||||||
|
roc__mainForHost_1_exposed_generic(&rocStr)
|
||||||
|
self.str = getSwiftString(rocStr: rocStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Text(self.str)
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@main
|
||||||
|
struct RocTestApp: App {
|
||||||
|
var body: some Scene {
|
||||||
|
WindowGroup {
|
||||||
|
ContentView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
examples/swiftui/platform/main.roc
Normal file
9
examples/swiftui/platform/main.roc
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
platform "swiftui-platform"
|
||||||
|
requires {} { main : Str }
|
||||||
|
exposes []
|
||||||
|
packages {}
|
||||||
|
imports []
|
||||||
|
provides [mainForHost]
|
||||||
|
|
||||||
|
mainForHost : Str
|
||||||
|
mainForHost = main
|
6
examples/swiftui/run.sh
Executable file
6
examples/swiftui/run.sh
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#! /usr/bin/env bash
|
||||||
|
|
||||||
|
cargo run -- build
|
||||||
|
mkdir -p SwiftUIDemo.app/Contents/MacOS/
|
||||||
|
mv swiftui SwiftUIDemo.app/Contents/MacOS/SwiftUIDemo
|
||||||
|
open SwiftUIDemo.app
|
Loading…
Add table
Add a link
Reference in a new issue