Skip to content

Commit b251dac

Browse files
committed
allow literal tuple also
Ecosystem has several uses of literal tuple generated by macro, so add the code to continue to support that also.
1 parent 9c7d4e1 commit b251dac

File tree

3 files changed

+40
-12
lines changed

3 files changed

+40
-12
lines changed

doc/src/manual/calling-c-and-fortran-code.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,8 @@ The arguments to [`ccall`](@ref) are:
10121012
name.
10131013
- Single name: `(:function_name,)` or `"function_name"` - uses default library lookup.
10141014
- Name with library: `(:function_name, "library")` - specifies both function and library.
1015-
- Symbol and string literals are automatically normalized to tuple form.
1015+
- Symbol, string, and tuple literal constants (not expressions that evaluate to those constants,
1016+
but actual literals) are automatically normalized to tuple form.
10161017
* **Pointer-based calls** (non-tuple syntax):
10171018
- Anything that is not a literal tuple expression specified above is assumed to be an
10181019
expression that evaluates to a function pointers at runtime.

src/julia-syntax.scm

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,12 +1093,7 @@
10931093
;; Already a tuple - keep as-is, validation will happen in C
10941094
((tuple-syntax? raw-name)
10951095
raw-name)
1096-
;; Normalize atoms like strings and quoted values into 1-element tuple, since they aren't pointers
1097-
((and (atom? raw-name) (not (symbol? raw-name)))
1098-
`(tuple ,raw-name))
1099-
((and (pair? raw-name) (quoted? raw-name))
1100-
`(tuple ,raw-name))
1101-
;; Otherwise it is a pointer expression
1096+
;; Otherwise it is an atom or pointer expression, which will be validated later in C
11021097
(else (expand-forms raw-name))))
11031098

11041099
;; insert calls to convert() in ccall, and pull out expressions that might

src/method.c

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,28 @@ static jl_value_t *resolve_definition_effects(jl_value_t *expr, jl_module_t *mod
175175
jl_task_t *ct = jl_current_task;
176176
jl_value_t *fptr = jl_exprarg(e, 0);
177177
// Handle dot expressions in tuple arguments for ccall by converting to GlobalRef eagerly
178-
if (jl_is_expr(fptr) && ((jl_expr_t*)fptr)->head == jl_symbol("tuple")) {
178+
jl_sym_t *tuple_sym = jl_symbol("tuple");
179+
if (jl_is_quotenode(fptr)) {
180+
if (jl_is_string(jl_quotenode_value(fptr)) || jl_is_tuple(jl_quotenode_value(fptr)))
181+
fptr = jl_quotenode_value(fptr);
182+
}
183+
if (jl_is_tuple(fptr)) {
184+
// convert literal Tuple to Expr tuple
185+
jl_expr_t *tupex = jl_exprn(tuple_sym, jl_nfields(fptr));
186+
jl_value_t *v = NULL;
187+
JL_GC_PUSH2(&tupex, &v);
188+
for (long i = 0; i < jl_nfields(fptr); i++) {
189+
v = jl_fieldref(fptr, i);
190+
if (!jl_is_string(v))
191+
v = jl_new_struct(jl_quotenode_type, v);
192+
jl_exprargset(tupex, i, v);
193+
}
194+
jl_exprargset(e, 0, tupex);
195+
fptr = (jl_value_t*)tupex;
196+
JL_GC_POP();
197+
}
198+
if (jl_is_expr(fptr) && ((jl_expr_t*)fptr)->head == tuple_sym) {
199+
// verify Expr tuple can be interpreted and handle
179200
jl_expr_t *tuple_expr = (jl_expr_t*)fptr;
180201
size_t nargs_tuple = jl_expr_nargs(tuple_expr);
181202
if (nargs_tuple == 0)
@@ -212,15 +233,26 @@ static jl_value_t *resolve_definition_effects(jl_value_t *expr, jl_module_t *mod
212233
}
213234
}
214235
else if (jl_is_quotenode(arg)) {
215-
jl_value_t *quoted_val = jl_quotenode_value(arg);
216-
if (!jl_is_symbol(quoted_val) && !jl_is_string(quoted_val))
217-
jl_type_error("ccall function name", (jl_value_t*)jl_symbol_type, quoted_val);
236+
if (i == 0) {
237+
// function name must be a symbol or string, library can be anything
238+
jl_value_t *quoted_val = jl_quotenode_value(arg);
239+
if (!jl_is_symbol(quoted_val) && !jl_is_string(quoted_val))
240+
jl_type_error("ccall function name", (jl_value_t*)jl_symbol_type, jl_quotenode_value(arg));
241+
}
218242
}
219243
else if (!jl_is_globalref(arg) && jl_isa_ast_node(arg)) {
220-
jl_type_error("ccall function name", (jl_value_t*)jl_symbol_type, arg);
244+
jl_type_error(i == 0 ? "ccall function name" : "ccall library name", (jl_value_t*)jl_symbol_type, arg);
221245
}
222246
}
223247
}
248+
else if (jl_is_string(fptr) || (jl_is_quotenode(fptr) && jl_is_symbol(jl_quotenode_value(fptr)))) {
249+
// convert String to Expr (String,)
250+
// convert QuoteNode(Symbol) to Expr (QuoteNode(Symbol),)
251+
jl_expr_t *tupex = jl_exprn(tuple_sym, 1);
252+
jl_exprargset(tupex, 0, fptr);
253+
jl_exprargset(e, 0, tupex);
254+
fptr = (jl_value_t*)tupex;
255+
}
224256
jl_value_t *rt = jl_exprarg(e, 1);
225257
jl_value_t *at = jl_exprarg(e, 2);
226258
if (!jl_is_type(rt)) {

0 commit comments

Comments
 (0)