Skip to content

Commit

Permalink
feat: kcl swift lib
Browse files Browse the repository at this point in the history
Signed-off-by: peefy <[email protected]>
  • Loading branch information
Peefy committed Jul 28, 2024
1 parent 8facb02 commit 0638deb
Show file tree
Hide file tree
Showing 17 changed files with 5,017 additions and 1 deletion.
52 changes: 52 additions & 0 deletions .github/workflows/swift-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: swift-test

on:
push:
branches:
- main
- master
tags:
- '*'
pull_request:
branches:
- main
paths:
- "swift/**"
- ".github/workflows/swift-test.yaml"
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true

permissions:
contents: read

jobs:
build-and-test:
defaults:
run:
working-directory: "swift"
strategy:
matrix:
os: [macos-12, macos-latest, ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Install dependencies
if: "contains(matrix.os, 'ubuntu-latest')"
run: |
sudo apt-get update
sudo apt-get install libgtest-dev ninja-build
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: 1.79
override: true
components: clippy, rustfmt
- name: Setup Swift toolchain
uses: swift-actions/setup-swift@v1
with:
swift-version: 5
- name: Build and run tests
run: make test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ _a.out_*.*
**/.DS_Store
**/.vscode
__pycache__
build
3 changes: 2 additions & 1 deletion spec/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ run:
protoc spec.proto --python_out ../python/kcl_lib/api
protoc spec.proto --go_out ../go/api
protoc spec.proto --csharp_out ../dotnet/KclLib/api
protoc spec.proto --cpp_out ../cpp/src/api
// brew install swift-protobuf
protoc spec.proto --swift_out=Visibility=Public:../swift/Sources/KclLib
12 changes: 12 additions & 0 deletions swift/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.netrc

/KclLib/.build
/KclLib/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
/KclLib/.swiftpm/config/registries.json
/KclLib/Sources/CKclLib/lib
11 changes: 11 additions & 0 deletions swift/.swift-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"version": 1,
"lineLength": 100,
"indentation": {
"spaces": 4
},
"maximumBlankLines": 1,
"respectsExistingLineBreaks": true,
"lineBreakBeforeControlFlowKeywords": true,
"lineBreakBeforeEachArgument": true
}
15 changes: 15 additions & 0 deletions swift/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "kcl-lib-c"
version = "0.10.0-alpha.1"
edition = "2021"
publish = false

[lib]
crate-type = ["cdylib", "staticlib"]
doc = false

[build-dependencies]
cbindgen = "0.26.0"

[dependencies]
kclvm-api = { git = "https://github.com/kcl-lang/kcl", version = "0.10.0-alpha.1" }
27 changes: 27 additions & 0 deletions swift/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
INCLUDE_DIR=./Sources/CKclLib/include
LIB_DIR=./Sources/CKclLib/lib
DIRS=$(INCLUDE_DIR) $(LIB_DIR)

.PHONY: all
all: build

.PHONY: build
build: cargo
swift build

.PHONY: cargo
cargo:
cargo build -r
cp ./target/release/libkcl_lib_c.a $(LIB_DIR)

.PHONY: test
test: cargo
swift test

$(DIRS):
mkdir -p $@

.PHONY: clean
clean:
cargo clean
rm -rf $(LIB_DIR)
37 changes: 37 additions & 0 deletions swift/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// swift-tools-version: 5.8
// The swift-tools-version declares the minimum version of Swift required to build this package.

import Foundation
import PackageDescription

let packageRoot = (#file as NSString).deletingLastPathComponent

let package = Package(
name: "KclLib",
products: [
.library(
name: "KclLib",
targets: ["KclLib"]
)
],
dependencies: [
.package(url: "https://github.com/apple/swift-protobuf.git", from: "1.27.0"),
],
targets: [
.systemLibrary(name: "CKclLib"),
.target(
name: "KclLib",
dependencies: [
"CKclLib",
.product(name: "SwiftProtobuf", package: "swift-protobuf")
],
linkerSettings: [
.unsafeFlags(["-L\(packageRoot)/Sources/CKclLib/lib"])
]
),
.testTarget(
name: "KclLibTests",
dependencies: ["KclLib"]
),
]
)
3 changes: 3 additions & 0 deletions swift/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# KCL Artifact Library for Swift

This repo is under development, PRs welcome!
22 changes: 22 additions & 0 deletions swift/Sources/CKclLib/include/kcl_lib_c.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef _KCL_FFI_H
#define _KCL_FFI_H

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

uintptr_t call_native(const uint8_t *name_ptr,
uintptr_t name_len,
const uint8_t *args_ptr,
uintptr_t args_len,
uint8_t *result_ptr);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

#endif /* _KCL_FFI_H */
6 changes: 6 additions & 0 deletions swift/Sources/CKclLib/module.modulemap
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module KclLib [system] {
header "include/kcl_lib_c.h"
link "kcl_lib_c"

export *
}
112 changes: 112 additions & 0 deletions swift/Sources/KclLib/API.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import Foundation
import SwiftProtobuf
import CKclLib

public class API: Service {
private static let ERROR_PREFIX = "ERROR:"

public init() {}

// Parses a single KCL file and returns its Abstract Syntax Tree (AST) as a JSON string.
public func parseFile(_ args: ParseFile_Args) -> ParseFile_Result {
return ParseFile_Result(serializedData: callNative(name: "KclvmService.ParseFile", args: args.serializedBytes()))
}

// Parses a KCL program and returns the Abstract Syntax Tree (AST) in JSON format.
public func parseProgram(_ args: ParseProgram_Args) -> ParseProgram_Result {
return ParseProgram_Result(serializedData: callNative(name: "KclvmService.ParseProgram", args: args.serializedBytes()))
}

// Loads a KCL package and retrieves AST, symbol, type, and definition information.
public func loadPackage(_ args: LoadPackage_Args) -> LoadPackage_Result {
return LoadPackage_Result(serializedData: callNative(name: "KclvmService.LoadPackage", args: args.serializedBytes()))
}

// Executes a KCL file with provided arguments.
public func execProgram(_ args: ExecProgram_Args) -> ExecProgram_Result {
return ExecProgram_Result(serializedData: callNative(name: "KclvmService.ExecProgram", args: args.serializedBytes()))
}

// Overrides specified elements in a KCL file according to given arguments.
public func overrideFile(_ args: OverrideFile_Args) -> OverrideFile_Result {
return OverrideFile_Result(serializedData: callNative(name: "KclvmService.OverrideFile", args: args.serializedBytes()))
}

// Lists all variables declared in a KCL file.
public func listVariables(_ args: ListVariables_Args) -> ListVariables_Result {
return ListVariables_Result(serializedData: callNative(name: "KclvmService.ListVariables", args: args.serializedBytes()))
}

// Lists all options defined in a KCL program.
public func listOptions(_ args: ParseProgram_Args) -> ListOptions_Result {
return ListOptions_Result(serializedData: callNative(name: "KclvmService.ListOptions", args: args.serializedBytes()))
}

// Retrieves the full schema type mapping for a KCL program.
public func getSchemaTypeMapping(_ args: GetSchemaTypeMapping_Args) -> GetSchemaTypeMapping_Result {
return GetSchemaTypeMapping_Result(serializedData: callNative(name: "KclvmService.GetSchemaTypeMapping", args: args.serializedBytes()))
}

// Formats source code according to KCL style guidelines.
public func formatCode(_ args: FormatCode_Args) -> FormatCode_Result {
return FormatCode_Result(serializedData: callNative(name: "KclvmService.FormatCode", args: args.serializedBytes()))
}

// Formats KCL files or directories to conform to style guidelines.
public func formatPath(_ args: FormatPath_Args) -> FormatPath_Result {
return FormatPath_Result(serializedData: callNative(name: "KclvmService.FormatPath", args: args.serializedBytes()))
}

// Runs linting checks on KCL files and reports errors and warnings.
public func lintPath(_ args: LintPath_Args) -> LintPath_Result {
return LintPath_Result(serializedData: callNative(name: "KclvmService.LintPath", args: args.serializedBytes()))
}

// Validates a data string against a schema defined in a KCL code string.
public func validateCode(_ args: ValidateCode_Args) -> ValidateCode_Result {
return ValidateCode_Result(serializedData: callNative(name: "KclvmService.ValidateCode", args: args.serializedBytes()))
}

// Builds configuration from settings files.
public func loadSettingsFiles(_ args: LoadSettingsFiles_Args) -> LoadSettingsFiles_Result {
return LoadSettingsFiles_Result(serializedData: callNative(name: "KclvmService.LoadSettingsFiles", args: args.serializedBytes()))
}

// Renames symbols across files within a KCL package.
public func rename(_ args: Rename_Args) -> Rename_Result {
return Rename_Result(serializedData: callNative(name: "KclvmService.Rename", args: args.serializedBytes()))
}

// Renames symbols in source code without modifying files directly.
public func renameCode(_ args: RenameCode_Args) -> RenameCode_Result {
return RenameCode_Result(serializedData: callNative(name: "KclvmService.RenameCode", args: args.serializedBytes()))
}

// Executes tests on KCL packages using specified test arguments.
public func test(_ args: Test_Args) -> Test_Result {
return Test_Result(serializedData: callNative(name: "KclvmService.Test", args: args.serializedBytes()))
}

// Updates dependencies for a KCL project based on defined specifications.
public func updateDependencies(_ args: UpdateDependencies_Args) -> UpdateDependencies_Result {
return UpdateDependencies_Result(serializedData: callNative(name: "KclvmService.UpdateDependencies", args: args.serializedBytes()))
}

// Retrieves version information about the KCL service.
public func getVersion(_ args: GetVersion_Args) -> GetVersion_Result {
return GetVersion_Result(serializedData: callNative(name: "KclvmService.GetVersion", args: args.serializedBytes()))
}

private func callNative(name: String, args: Data) -> Data {
// Convert name to byte array
let nameBytes = [UInt8](name.utf8)
var resultBuf = [UInt8](repeating: 0, count: 2048 * 2048)
let resultLength = call_native(nameBytes, nameBytes.count, [UInt8](args), args.count, &resultBuf)
let result = Data(bytes: resultBuf, count: resultLength)
let resultString = String(bytes: result, encoding: .utf8) ?? ""
if resultString.isEmpty || !resultString.hasPrefix(API.ERROR_PREFIX) {
return result
}
fatalError(resultString.dropFirst(API.ERROR_PREFIX.count))
}
}
58 changes: 58 additions & 0 deletions swift/Sources/KclLib/Service.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import Foundation

// Define the protocol for services that manage various operations on KCL programs.
public protocol Service {
// Parses a single KCL file and returns its Abstract Syntax Tree (AST) as a JSON string.
func parseFile(_ args: ParseFile_Args) -> ParseFile_Result

// Parses a KCL program and returns the Abstract Syntax Tree (AST) in JSON format.
func parseProgram(_ args: ParseProgram_Args) -> ParseProgram_Result

// Loads a KCL package and retrieves AST, symbol, type, and definition information.
func loadPackage(_ args: LoadPackage_Args) -> LoadPackage_Result

// Executes a KCL file with provided arguments.
func execProgram(_ args: ExecProgram_Args) -> ExecProgram_Result

// Overrides specified elements in a KCL file according to given arguments.
func overrideFile(_ args: OverrideFile_Args) -> OverrideFile_Result

// Lists all variables declared in a KCL file.
func listVariables(_ args: ListVariables_Args) -> ListVariables_Result

// Lists all options defined in a KCL program.
func listOptions(_ args: ParseProgram_Args) -> ListOptions_Result

// Retrieves the full schema type mapping for a KCL program.
func getSchemaTypeMapping(_ args: GetSchemaTypeMapping_Args) -> GetSchemaTypeMapping_Result

// Formats source code according to KCL style guidelines.
func formatCode(_ args: FormatCode_Args) -> FormatCode_Result

// Formats KCL files or directories to conform to style guidelines.
func formatPath(_ args: FormatPath_Args) -> FormatPath_Result

// Runs linting checks on KCL files and reports errors and warnings.
func lintPath(_ args: LintPath_Args) -> LintPath_Result

// Validates a data string against a schema defined in a KCL code string.
func validateCode(_ args: ValidateCode_Args) -> ValidateCode_Result

// Builds configuration from settings files.
func loadSettingsFiles(_ args: LoadSettingsFiles_Args) -> LoadSettingsFiles_Result

// Renames symbols across files within a KCL package.
func rename(_ args: Rename_Args) -> Rename_Result

// Renames symbols in source code without modifying files directly.
func renameCode(_ args: RenameCode_Args) -> RenameCode_Result

// Executes tests on KCL packages using specified test arguments.
func test(_ args: Test_Args) -> Test_Result

// Updates dependencies for a KCL project based on defined specifications.
func updateDependencies(_ args: UpdateDependencies_Args) -> UpdateDependencies_Result

// Retrieves version information about the KCL service.
func getVersion(_ args: GetVersion_Args) -> GetVersion_Result
}
Loading

0 comments on commit 0638deb

Please sign in to comment.