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
|
Encoding: UTF-8
|
||||||
Roxygen: list(markdown = TRUE)
|
Roxygen: list(markdown = TRUE)
|
||||||
RoxygenNote: 7.3.1
|
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
|
# Generated by roxygen2: do not edit by hand
|
||||||
|
|
||||||
S3method(print,ts_object)
|
S3method(print,ts_object)
|
||||||
|
S3method(ts_compile,character)
|
||||||
|
S3method(ts_compile,default)
|
||||||
|
S3method(ts_compile,ts_function)
|
||||||
export(ts_character)
|
export(ts_character)
|
||||||
export(ts_compile)
|
export(ts_compile)
|
||||||
|
export(ts_dataframe)
|
||||||
|
export(ts_factor)
|
||||||
export(ts_function)
|
export(ts_function)
|
||||||
export(ts_integer)
|
export(ts_integer)
|
||||||
|
export(ts_list)
|
||||||
export(ts_logical)
|
export(ts_logical)
|
||||||
export(ts_numeric)
|
export(ts_numeric)
|
||||||
|
|||||||
53
R/compile.R
53
R/compile.R
@ -1,11 +1,58 @@
|
|||||||
#' @export
|
#' @export
|
||||||
ts_compile <- function(f) {
|
ts_compile <- function(f, file = NULL, ...) {
|
||||||
name <- deparse(substitute(f))
|
UseMethod("ts_compile")
|
||||||
|
}
|
||||||
|
|
||||||
|
#' @export
|
||||||
|
ts_compile.ts_function <- function(f, file = NULL, name = deparse(substitute(f))) {
|
||||||
inputs <- attr(f, "args")
|
inputs <- attr(f, "args")
|
||||||
result <- attr(f, "result")
|
result <- attr(f, "result")
|
||||||
|
|
||||||
inputs <- sapply(inputs, \(x) x$type)
|
inputs <- sapply(inputs, \(x) x$type)
|
||||||
fn_args <- paste(names(inputs), inputs, sep = ": ") |>
|
fn_args <- paste(names(inputs), inputs, sep = ": ") |>
|
||||||
paste(collapse = ", ")
|
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) {
|
ts_logical <- function(n = -1L) {
|
||||||
object(
|
object(
|
||||||
n_type(n, "boolean"),
|
n_type(n, "boolean"),
|
||||||
n_type_fun(n, "Logical"),
|
n_type_fun(n, "RTYPE.Logical"),
|
||||||
check = function(x) {
|
check = function(x) {
|
||||||
if (!is.logical(x)) stop("Expected a boolean")
|
if (!is.logical(x)) stop("Expected a boolean")
|
||||||
if (n > 0 && length(x) != n) stop("Expected a boolean of length ", n)
|
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) {
|
ts_integer <- function(n = -1L) {
|
||||||
object(
|
object(
|
||||||
n_type(n, "number"),
|
n_type(n, "number"),
|
||||||
n_type_fun(n, "Integer"),
|
n_type_fun(n, "RTYPE.Integer"),
|
||||||
check = function(x) {
|
check = function(x) {
|
||||||
if (!is.integer(x)) stop("Expected an integer")
|
if (!is.integer(x)) stop("Expected an integer")
|
||||||
if (n > 0 && length(x) != n) stop("Expected an integer of length ", n)
|
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) {
|
ts_numeric <- function(n = -1L) {
|
||||||
object(
|
object(
|
||||||
n_type(n, "number"),
|
n_type(n, "number"),
|
||||||
n_type_fun(n, "Numeric"),
|
n_type_fun(n, "RTYPE.Numeric"),
|
||||||
check = function(x) {
|
check = function(x) {
|
||||||
if (!is.numeric(x)) stop("Expected a number", call. = FALSE)
|
if (!is.numeric(x)) stop("Expected a number", call. = FALSE)
|
||||||
if (n > 0 && length(x) != n) {
|
if (n > 0 && length(x) != n) {
|
||||||
@ -97,7 +97,7 @@ ts_numeric <- function(n = -1L) {
|
|||||||
ts_character <- function(n = -1L) {
|
ts_character <- function(n = -1L) {
|
||||||
object(
|
object(
|
||||||
n_type(n, "string"),
|
n_type(n, "string"),
|
||||||
n_type_fun(n, "Character"),
|
n_type_fun(n, "RTYPE.Character"),
|
||||||
check = function(x) {
|
check = function(x) {
|
||||||
if (!is.character(x)) stop("Expected a string")
|
if (!is.character(x)) stop("Expected a string")
|
||||||
if (n > 0 && length(x) != n) stop("Expected a string of length ", n)
|
if (n > 0 && length(x) != n) stop("Expected a string of length ", n)
|
||||||
|
|||||||
@ -102,5 +102,7 @@ myfun(1:5)
|
|||||||
|
|
||||||
myfun("hello world")
|
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")
|
myfun("hello world")
|
||||||
#> Error: Expected a number
|
#> Error: Expected a number
|
||||||
|
|
||||||
ts_compile(myfun)
|
cat(readLines("tests/testthat/app/app.R"), sep = "\n")
|
||||||
#> const myfun = (x: number | number[]) => Promise<Robj.Numeric<1>)>;
|
#> 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