1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: interface_call()

This commit is contained in:
Alexander Medvednikov 2020-05-02 10:10:52 +02:00
parent aa9bb6f71a
commit 06173834c0
2 changed files with 45 additions and 32 deletions

View File

@ -36,11 +36,11 @@ const (
'unsigned',
'void',
'volatile',
'while',
//'new'
'while'
]
)
// 'new'
fn foo(t token.Token) {
util.full_hash()
}
@ -2202,9 +2202,10 @@ string _STR(const char *fmt, int nfmts, ...) {
int k = strlen(fmt);
bool is_fspec = false;
for (int j=0; j<k; j++) {
if (fmt[j] == '+"'%'"+') {
if (fmt[j] == ' +
"'%'" + ') {
j++;
if(fmt[j] != '+"'%'"+') {
if(fmt[j] != ' + "'%'" + ') {
is_fspec = true;
break;
}
@ -2213,17 +2214,22 @@ string _STR(const char *fmt, int nfmts, ...) {
if (is_fspec) {
char f = fmt[k-1];
char fup = f & 0xdf; // toupper
bool l = fmt[k-2] == '+"'l'"+';
bool ll = l && fmt[k-3] == '+"'l'"+';
if (f == '+"'u'"+' || fup == '+"'X'"+' || f == '+"'o'"+' || f == '+"'d'"+' || f == '+"'c'"+') { // int...
bool l = fmt[k-2] == ' +
"'l'" + ';
bool ll = l && fmt[k-3] == ' + "'l'" + ';
if (f == ' + "'u'" + ' || fup == ' +
"'X'" + ' || f == ' + "'o'" + ' || f == ' + "'d'" + ' || f == ' + "'c'" + ') { // int...
if (ll) _STR_PRINT_ARG(fmt, &buf, &nbytes, &memsize, k+16, va_arg(argptr, long long));
else if (l) _STR_PRINT_ARG(fmt, &buf, &nbytes, &memsize, k+10, va_arg(argptr, long));
else _STR_PRINT_ARG(fmt, &buf, &nbytes, &memsize, k+8, va_arg(argptr, int));
} else if (fup >= '+"'E'"+' && fup <= '+"'G'"+') { // floating point
} else if (fup >= ' +
"'E'" + ' && fup <= ' + "'G'" + ') { // floating point
_STR_PRINT_ARG(fmt, &buf, &nbytes, &memsize, k+10, va_arg(argptr, double));
} else if (f == '+"'s'"+') { // v string
} else if (f == ' +
"'s'" + ') { // v string
string s = va_arg(argptr, string);
if (fmt[k-4] == '+"'*'"+') { // %*.*s
if (fmt[k-4] == ' + "'*'" +
') { // %*.*s
int fwidth = va_arg(argptr, int);
if (fwidth < 0)
fwidth -= (s.len - utf8_str_len(s));
@ -2460,9 +2466,8 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
fspec = `d`
} else if node.expr_types[i].is_unsigned() {
fspec = `u`
} else if node.expr_types[i] in [table.string_type, table.bool_type] ||
sym.kind in [.enum_, .array, .array_fixed, .struct_, .map] ||
g.typ(node.expr_types[i]).starts_with('Option') ||
} else if node.expr_types[i] in [table.string_type, table.bool_type] || sym.kind in
[.enum_, .array, .array_fixed, .struct_, .map] || g.typ(node.expr_types[i]).starts_with('Option') ||
sym.has_method('str') {
fspec = `s`
} else {
@ -2473,17 +2478,17 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
fields := fmt.split('.')
// validate format
// only floats should have precision specifier
if fields.len > 2 || fields.len == 2 && !(node.expr_types[i].is_float()) ||
node.expr_types[i].is_signed() && !(fspec in [`d`, `c`, `x`, `X`, `o`]) ||
node.expr_types[i].is_unsigned() && !(fspec in [`u`, `x`, `X`, `o`, `c`]) ||
node.expr_types[i].is_float() && !(fspec in [`E`, `F`, `G`, `e`, `f`, `g`, `e`]) {
if fields.len > 2 || fields.len == 2 && !(node.expr_types[i].is_float()) || node.expr_types[i].is_signed() &&
!(fspec in [`d`, `c`, `x`, `X`, `o`]) || node.expr_types[i].is_unsigned() && !(fspec in [`u`,
`x`, `X`, `o`, `c`]) || node.expr_types[i].is_float() && !(fspec in [`E`, `F`, `G`, `e`, `f`,
`g`, `e`]) {
verror('illegal format specifier ${fspec:c} for type ${g.table.get_type_name(node.expr_types[i])}')
}
// make sure that format paramters are valid numbers
for j, f in fields {
for k, c in f {
if (c < `0` || c > `9`) &&
!(j == 0 && k == 0 && (node.expr_types[i].is_number() && c == `+` || c == `-`)) {
if (c < `0` || c > `9`) && !(j == 0 && k == 0 && (node.expr_types[i].is_number() &&
c == `+` || c == `-`)) {
verror('illegal character ${c:c} in format specifier ${fmt}')
}
}
@ -2506,8 +2511,8 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
g.write('$fmt${fspec:c}')
} else if node.expr_types[i].is_int() {
if fspec == `c` {
if node.expr_types[i].idx() in [table.i64_type_idx table.f64_type_idx] {
verror("64 bit integer types cannot be interpolated as character")
if node.expr_types[i].idx() in [table.i64_type_idx, table.f64_type_idx] {
verror('64 bit integer types cannot be interpolated as character')
} else {
g.write('${fmt}c')
}
@ -2565,11 +2570,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
}
} else if sym.has_method('str') || sym.kind in [.array, .array_fixed, .map, .struct_] {
is_p := node.expr_types[i].is_ptr()
val_type := if is_p {
node.expr_types[i].deref()
} else {
node.expr_types[i]
}
val_type := if is_p { node.expr_types[i].deref() } else { node.expr_types[i] }
str_fn_name := g.gen_str_for_type(val_type)
if is_p {
g.write('string_add(_SLIT("&"), ${str_fn_name}(*(')
@ -3550,9 +3551,12 @@ fn (mut g Gen) array_init(it ast.ArrayInit) {
if it.is_interface {
// sym := g.table.get_type_symbol(it.interface_types[i])
// isym := g.table.get_type_symbol(it.interface_type)
/*
interface_styp := g.typ(it.interface_type)
styp := g.typ(it.interface_types[i])
g.write('I_${styp}_to_${interface_styp}(')
*/
g.interface_call(it.interface_types[i], it.interface_type)
}
g.expr(expr)
if it.is_interface {
@ -3562,3 +3566,11 @@ fn (mut g Gen) array_init(it ast.ArrayInit) {
}
g.write('\n})')
}
// `ui.foo(button)` =>
// `ui__foo(I_ui__Button_to_ui__Widget(` ...
fn (g &Gen) interface_call(typ, interface_type table.Type) {
interface_styp := g.typ(interface_type).replace('*', '')
styp := g.typ(typ).replace('*', '')
g.write('I_${styp}_to_${interface_styp}(')
}

View File

@ -508,10 +508,11 @@ fn (mut g Gen) call_args(args []ast.CallArg, expected_types []table.Type) {
// Cast a type to interface
// `foo(dog)` => `foo(I_Dog_to_Animal(dog))`
exp_sym := g.table.get_type_symbol(expected_types[arg_no])
exp_styp := g.typ(expected_types[arg_no]) // g.table.get_type_symbol(expected_types[arg_no])
styp := g.typ(arg.typ) // g.table.get_type_symbol(arg.typ)
// exp_styp := g.typ(expected_types[arg_no]) // g.table.get_type_symbol(expected_types[arg_no])
// styp := g.typ(arg.typ) // g.table.get_type_symbol(arg.typ)
if exp_sym.kind == .interface_ {
g.write('I_${styp}_to_${exp_styp}(')
g.interface_call(arg.typ, expected_types[arg_no])
// g.write('/*Z*/I_${styp}_to_${exp_styp}(')
is_interface = true
}
}