compile a file of funtions
This commit is contained in:
parent
e9751e5c0a
commit
f54acd6e8a
@ -10,3 +10,6 @@ License: MIT + file LICENSE
|
||||
Encoding: UTF-8
|
||||
Roxygen: list(markdown = TRUE)
|
||||
RoxygenNote: 7.3.1
|
||||
Suggests:
|
||||
testthat (>= 3.0.0)
|
||||
Config/testthat/edition: 3
|
||||
|
||||
@ -1,9 +1,15 @@
|
||||
# Generated by roxygen2: do not edit by hand
|
||||
|
||||
S3method(print,ts_object)
|
||||
S3method(ts_compile,character)
|
||||
S3method(ts_compile,default)
|
||||
S3method(ts_compile,ts_function)
|
||||
export(ts_character)
|
||||
export(ts_compile)
|
||||
export(ts_dataframe)
|
||||
export(ts_factor)
|
||||
export(ts_function)
|
||||
export(ts_integer)
|
||||
export(ts_list)
|
||||
export(ts_logical)
|
||||
export(ts_numeric)
|
||||
|
||||
53
R/compile.R
53
R/compile.R
@ -1,11 +1,58 @@
|
||||
#' @export
|
||||
ts_compile <- function(f) {
|
||||
name <- deparse(substitute(f))
|
||||
ts_compile <- function(f, file = NULL, ...) {
|
||||
UseMethod("ts_compile")
|
||||
}
|
||||
|
||||
#' @export
|
||||
ts_compile.ts_function <- function(f, file = NULL, name = deparse(substitute(f))) {
|
||||
inputs <- attr(f, "args")
|
||||
result <- attr(f, "result")
|
||||
|
||||
inputs <- sapply(inputs, \(x) x$type)
|
||||
fn_args <- paste(names(inputs), inputs, sep = ": ") |>
|
||||
paste(collapse = ", ")
|
||||
cat(sprintf("const %s = (%s) => Promise<%s>;", name, fn_args, result$type_fn), "\n")
|
||||
sprintf("const %s = (%s) => Promise<%s>;", name, fn_args, result$type_fn)
|
||||
}
|
||||
|
||||
#' @export
|
||||
ts_compile.character <- function(
|
||||
f,
|
||||
file = sprintf("%s.ts", tools::file_path_sans_ext(f))) {
|
||||
if (length(f) > 1) {
|
||||
return(sapply(f, ts_compile))
|
||||
}
|
||||
|
||||
if (!file.exists(f)) {
|
||||
warning(sprintf("File not found: %s", f))
|
||||
return()
|
||||
}
|
||||
e <- new.env()
|
||||
source(f, local = e)
|
||||
|
||||
x <- sapply(ls(e), \(x) ts_compile(e[[x]], file = file, name = x))
|
||||
|
||||
# find any RTYPE.[type] and grab types
|
||||
types <- unique(
|
||||
gsub(
|
||||
"RTYPE\\.(\\w+)", "\\1",
|
||||
unlist(regmatches(x, gregexpr("RTYPE\\.\\w+", x)))
|
||||
)
|
||||
)
|
||||
x <- gsub("RTYPE\\.", "", x)
|
||||
|
||||
cat(
|
||||
sprintf(
|
||||
"import type { %s } from 'rserve-ts';\n\n",
|
||||
paste(types, collapse = ", ")
|
||||
),
|
||||
file = file
|
||||
)
|
||||
cat(x, sep = "\n", file = file, append = TRUE)
|
||||
|
||||
invisible()
|
||||
}
|
||||
|
||||
#' @export
|
||||
ts_compile.default <- function(f) {
|
||||
warning("Not supported")
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ n_type_fun <- function(n, type) {
|
||||
ts_logical <- function(n = -1L) {
|
||||
object(
|
||||
n_type(n, "boolean"),
|
||||
n_type_fun(n, "Logical"),
|
||||
n_type_fun(n, "RTYPE.Logical"),
|
||||
check = function(x) {
|
||||
if (!is.logical(x)) stop("Expected a boolean")
|
||||
if (n > 0 && length(x) != n) stop("Expected a boolean of length ", n)
|
||||
@ -69,7 +69,7 @@ ts_logical <- function(n = -1L) {
|
||||
ts_integer <- function(n = -1L) {
|
||||
object(
|
||||
n_type(n, "number"),
|
||||
n_type_fun(n, "Integer"),
|
||||
n_type_fun(n, "RTYPE.Integer"),
|
||||
check = function(x) {
|
||||
if (!is.integer(x)) stop("Expected an integer")
|
||||
if (n > 0 && length(x) != n) stop("Expected an integer of length ", n)
|
||||
@ -82,7 +82,7 @@ ts_integer <- function(n = -1L) {
|
||||
ts_numeric <- function(n = -1L) {
|
||||
object(
|
||||
n_type(n, "number"),
|
||||
n_type_fun(n, "Numeric"),
|
||||
n_type_fun(n, "RTYPE.Numeric"),
|
||||
check = function(x) {
|
||||
if (!is.numeric(x)) stop("Expected a number", call. = FALSE)
|
||||
if (n > 0 && length(x) != n) {
|
||||
@ -97,7 +97,7 @@ ts_numeric <- function(n = -1L) {
|
||||
ts_character <- function(n = -1L) {
|
||||
object(
|
||||
n_type(n, "string"),
|
||||
n_type_fun(n, "Character"),
|
||||
n_type_fun(n, "RTYPE.Character"),
|
||||
check = function(x) {
|
||||
if (!is.character(x)) stop("Expected a string")
|
||||
if (n > 0 && length(x) != n) stop("Expected a string of length ", n)
|
||||
|
||||
@ -102,5 +102,7 @@ myfun(1:5)
|
||||
|
||||
myfun("hello world")
|
||||
|
||||
ts_compile(myfun)
|
||||
cat(readLines("tests/testthat/app/app.R"), sep = "\n")
|
||||
|
||||
ts_compile("tests/testthat/app/app.R", file = "")
|
||||
```
|
||||
|
||||
15
README.md
15
README.md
@ -98,6 +98,17 @@ myfun(1:5)
|
||||
myfun("hello world")
|
||||
#> Error: Expected a number
|
||||
|
||||
ts_compile(myfun)
|
||||
#> const myfun = (x: number | number[]) => Promise<Robj.Numeric<1>)>;
|
||||
cat(readLines("tests/testthat/app/app.R"), sep = "\n")
|
||||
#> library(ts)
|
||||
#>
|
||||
#> fn_mean <- ts_function(mean, x = ts_numeric(), result = ts_numeric(1))
|
||||
#> fn_first <- ts_function(function(x) x[1],
|
||||
#> x = ts_character(-1), result = ts_character(1)
|
||||
#> )
|
||||
|
||||
ts_compile("tests/testthat/app/app.R", file = "")
|
||||
#> import type { Character, Numeric } from 'rserve-ts';
|
||||
#>
|
||||
#> const fn_first = (x: string | string[]) => Promise<Character<1>)>;
|
||||
#> const fn_mean = (x: number | number[]) => Promise<Numeric<1>)>;
|
||||
```
|
||||
|
||||
25
man/object.Rd
Normal file
25
man/object.Rd
Normal file
@ -0,0 +1,25 @@
|
||||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/types.R
|
||||
\name{object}
|
||||
\alias{object}
|
||||
\title{Typed object}
|
||||
\usage{
|
||||
object(
|
||||
type = "any",
|
||||
type_fn = "any",
|
||||
default = NULL,
|
||||
check = function() stop("Not implemented")
|
||||
)
|
||||
}
|
||||
\arguments{
|
||||
\item{type}{The type of the object that Typescript expect to send to R.}
|
||||
|
||||
\item{type_fn}{The type of the object that Typescript expects to recieve from R.}
|
||||
|
||||
\item{default}{The default value of the object.}
|
||||
|
||||
\item{check}{A function that checks the object and returns it if it is valid. This operates on the R side and is mostly for development and debugging purposes. It is up to the developer to ensure that all functions return the correct type of object always.}
|
||||
}
|
||||
\description{
|
||||
This is the base type for all typed objects. It is not meant to be used directly.
|
||||
}
|
||||
11
man/ts_dataframe.Rd
Normal file
11
man/ts_dataframe.Rd
Normal file
@ -0,0 +1,11 @@
|
||||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/types.R
|
||||
\name{ts_dataframe}
|
||||
\alias{ts_dataframe}
|
||||
\title{Typed dataframe}
|
||||
\usage{
|
||||
ts_dataframe(...)
|
||||
}
|
||||
\description{
|
||||
This is essentially a list, but the elements must have names and are all the same length.
|
||||
}
|
||||
14
man/ts_factor.Rd
Normal file
14
man/ts_factor.Rd
Normal file
@ -0,0 +1,14 @@
|
||||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/types.R
|
||||
\name{ts_factor}
|
||||
\alias{ts_factor}
|
||||
\title{Typed factor}
|
||||
\usage{
|
||||
ts_factor(levels = NULL)
|
||||
}
|
||||
\arguments{
|
||||
\item{levels}{A character vector of levels (optional).}
|
||||
}
|
||||
\description{
|
||||
Factors are integers with labels. On the JS side, these are \emph{always} represented as a string array (even if only one value - yay!).
|
||||
}
|
||||
11
man/ts_list.Rd
Normal file
11
man/ts_list.Rd
Normal file
@ -0,0 +1,11 @@
|
||||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/types.R
|
||||
\name{ts_list}
|
||||
\alias{ts_list}
|
||||
\title{Typed list}
|
||||
\usage{
|
||||
ts_list(values = NULL)
|
||||
}
|
||||
\description{
|
||||
A list is a vector of other robjects, which may or may not be named.
|
||||
}
|
||||
12
tests/testthat.R
Normal file
12
tests/testthat.R
Normal file
@ -0,0 +1,12 @@
|
||||
# This file is part of the standard setup for testthat.
|
||||
# It is recommended that you do not modify it.
|
||||
#
|
||||
# Where should you do additional test configuration?
|
||||
# Learn more about the roles of various files in:
|
||||
# * https://r-pkgs.org/testing-design.html#sec-tests-files-overview
|
||||
# * https://testthat.r-lib.org/articles/special-files.html
|
||||
|
||||
library(testthat)
|
||||
library(ts)
|
||||
|
||||
test_check("ts")
|
||||
6
tests/testthat/app/app.R
Normal file
6
tests/testthat/app/app.R
Normal file
@ -0,0 +1,6 @@
|
||||
library(ts)
|
||||
|
||||
fn_mean <- ts_function(mean, x = ts_numeric(), result = ts_numeric(1))
|
||||
fn_first <- ts_function(function(x) x[1],
|
||||
x = ts_character(-1), result = ts_character(1)
|
||||
)
|
||||
4
tests/testthat/app/app.ts
Normal file
4
tests/testthat/app/app.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import { types } from 'rserve-ts';
|
||||
|
||||
const fn_first = (x: string | string[]) => Promise<RTYPE.Character<1>)>;
|
||||
const fn_mean = (x: number | number[]) => Promise<RTYPE.Numeric<1>)>;
|
||||
Loading…
x
Reference in New Issue
Block a user